diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2012-01-16 15:04:48 -0500 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2012-01-16 15:04:48 -0500 |
commit | e4d8ec0f65b91bfb4984a4927632ded95f9825ad (patch) | |
tree | 4727c977803093ec5cdf93da4fcab34cc8de8ecf /fs/btrfs | |
parent | 70922617b0099f420deceb53d5dc7f4fb30d08d0 (diff) |
Btrfs: implement online profile changing
Profile changing is done by launching a balance with
BTRFS_BALANCE_CONVERT bits set and target fields of respective
btrfs_balance_args structs initialized. Profile reducing code in this
case will pick restriper's target profile if it's available instead of
doing a blind reduce. If target profile is not yet available it goes
back to a plain reduce.
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 56 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 69 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 5 |
3 files changed, 129 insertions, 1 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a1a18ea7b6c6..e6a832e3e647 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -3030,7 +3030,9 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | |||
3030 | /* | 3030 | /* |
3031 | * @flags: available profiles in extended format (see ctree.h) | 3031 | * @flags: available profiles in extended format (see ctree.h) |
3032 | * | 3032 | * |
3033 | * Returns reduced profile in chunk format. | 3033 | * Returns reduced profile in chunk format. If profile changing is in |
3034 | * progress (either running or paused) picks the target profile (if it's | ||
3035 | * already available), otherwise falls back to plain reducing. | ||
3034 | */ | 3036 | */ |
3035 | u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) | 3037 | u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) |
3036 | { | 3038 | { |
@@ -3042,6 +3044,34 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) | |||
3042 | u64 num_devices = root->fs_info->fs_devices->rw_devices + | 3044 | u64 num_devices = root->fs_info->fs_devices->rw_devices + |
3043 | root->fs_info->fs_devices->missing_devices; | 3045 | root->fs_info->fs_devices->missing_devices; |
3044 | 3046 | ||
3047 | /* pick restriper's target profile if it's available */ | ||
3048 | spin_lock(&root->fs_info->balance_lock); | ||
3049 | if (root->fs_info->balance_ctl) { | ||
3050 | struct btrfs_balance_control *bctl = root->fs_info->balance_ctl; | ||
3051 | u64 tgt = 0; | ||
3052 | |||
3053 | if ((flags & BTRFS_BLOCK_GROUP_DATA) && | ||
3054 | (bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) && | ||
3055 | (flags & bctl->data.target)) { | ||
3056 | tgt = BTRFS_BLOCK_GROUP_DATA | bctl->data.target; | ||
3057 | } else if ((flags & BTRFS_BLOCK_GROUP_SYSTEM) && | ||
3058 | (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) && | ||
3059 | (flags & bctl->sys.target)) { | ||
3060 | tgt = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target; | ||
3061 | } else if ((flags & BTRFS_BLOCK_GROUP_METADATA) && | ||
3062 | (bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) && | ||
3063 | (flags & bctl->meta.target)) { | ||
3064 | tgt = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target; | ||
3065 | } | ||
3066 | |||
3067 | if (tgt) { | ||
3068 | spin_unlock(&root->fs_info->balance_lock); | ||
3069 | flags = tgt; | ||
3070 | goto out; | ||
3071 | } | ||
3072 | } | ||
3073 | spin_unlock(&root->fs_info->balance_lock); | ||
3074 | |||
3045 | if (num_devices == 1) | 3075 | if (num_devices == 1) |
3046 | flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0); | 3076 | flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0); |
3047 | if (num_devices < 4) | 3077 | if (num_devices < 4) |
@@ -3065,6 +3095,7 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) | |||
3065 | flags &= ~BTRFS_BLOCK_GROUP_RAID0; | 3095 | flags &= ~BTRFS_BLOCK_GROUP_RAID0; |
3066 | } | 3096 | } |
3067 | 3097 | ||
3098 | out: | ||
3068 | /* extended -> chunk profile */ | 3099 | /* extended -> chunk profile */ |
3069 | flags &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE; | 3100 | flags &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE; |
3070 | return flags; | 3101 | return flags; |
@@ -6795,6 +6826,29 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags) | |||
6795 | u64 stripped = BTRFS_BLOCK_GROUP_RAID0 | | 6826 | u64 stripped = BTRFS_BLOCK_GROUP_RAID0 | |
6796 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; | 6827 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10; |
6797 | 6828 | ||
6829 | if (root->fs_info->balance_ctl) { | ||
6830 | struct btrfs_balance_control *bctl = root->fs_info->balance_ctl; | ||
6831 | u64 tgt = 0; | ||
6832 | |||
6833 | /* pick restriper's target profile and return */ | ||
6834 | if (flags & BTRFS_BLOCK_GROUP_DATA && | ||
6835 | bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) { | ||
6836 | tgt = BTRFS_BLOCK_GROUP_DATA | bctl->data.target; | ||
6837 | } else if (flags & BTRFS_BLOCK_GROUP_SYSTEM && | ||
6838 | bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) { | ||
6839 | tgt = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target; | ||
6840 | } else if (flags & BTRFS_BLOCK_GROUP_METADATA && | ||
6841 | bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) { | ||
6842 | tgt = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target; | ||
6843 | } | ||
6844 | |||
6845 | if (tgt) { | ||
6846 | /* extended -> chunk profile */ | ||
6847 | tgt &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE; | ||
6848 | return tgt; | ||
6849 | } | ||
6850 | } | ||
6851 | |||
6798 | /* | 6852 | /* |
6799 | * we add in the count of missing devices because we want | 6853 | * we add in the count of missing devices because we want |
6800 | * to make sure that any RAID levels on a degraded FS | 6854 | * to make sure that any RAID levels on a degraded FS |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index e86c9e4fe51e..f08210e83339 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -2438,6 +2438,75 @@ int btrfs_balance(struct btrfs_balance_control *bctl, | |||
2438 | } | 2438 | } |
2439 | } | 2439 | } |
2440 | 2440 | ||
2441 | /* | ||
2442 | * Profile changing sanity checks. Skip them if a simple | ||
2443 | * balance is requested. | ||
2444 | */ | ||
2445 | if (!((bctl->data.flags | bctl->sys.flags | bctl->meta.flags) & | ||
2446 | BTRFS_BALANCE_ARGS_CONVERT)) | ||
2447 | goto do_balance; | ||
2448 | |||
2449 | allowed = BTRFS_AVAIL_ALLOC_BIT_SINGLE; | ||
2450 | if (fs_info->fs_devices->num_devices == 1) | ||
2451 | allowed |= BTRFS_BLOCK_GROUP_DUP; | ||
2452 | else if (fs_info->fs_devices->num_devices < 4) | ||
2453 | allowed |= (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1); | ||
2454 | else | ||
2455 | allowed |= (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 | | ||
2456 | BTRFS_BLOCK_GROUP_RAID10); | ||
2457 | |||
2458 | if (!profile_is_valid(bctl->data.target, 1) || | ||
2459 | bctl->data.target & ~allowed) { | ||
2460 | printk(KERN_ERR "btrfs: unable to start balance with target " | ||
2461 | "data profile %llu\n", | ||
2462 | (unsigned long long)bctl->data.target); | ||
2463 | ret = -EINVAL; | ||
2464 | goto out; | ||
2465 | } | ||
2466 | if (!profile_is_valid(bctl->meta.target, 1) || | ||
2467 | bctl->meta.target & ~allowed) { | ||
2468 | printk(KERN_ERR "btrfs: unable to start balance with target " | ||
2469 | "metadata profile %llu\n", | ||
2470 | (unsigned long long)bctl->meta.target); | ||
2471 | ret = -EINVAL; | ||
2472 | goto out; | ||
2473 | } | ||
2474 | if (!profile_is_valid(bctl->sys.target, 1) || | ||
2475 | bctl->sys.target & ~allowed) { | ||
2476 | printk(KERN_ERR "btrfs: unable to start balance with target " | ||
2477 | "system profile %llu\n", | ||
2478 | (unsigned long long)bctl->sys.target); | ||
2479 | ret = -EINVAL; | ||
2480 | goto out; | ||
2481 | } | ||
2482 | |||
2483 | if (bctl->data.target & BTRFS_BLOCK_GROUP_DUP) { | ||
2484 | printk(KERN_ERR "btrfs: dup for data is not allowed\n"); | ||
2485 | ret = -EINVAL; | ||
2486 | goto out; | ||
2487 | } | ||
2488 | |||
2489 | /* allow to reduce meta or sys integrity only if force set */ | ||
2490 | allowed = BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1 | | ||
2491 | BTRFS_BLOCK_GROUP_RAID10; | ||
2492 | if (((bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) && | ||
2493 | (fs_info->avail_system_alloc_bits & allowed) && | ||
2494 | !(bctl->sys.target & allowed)) || | ||
2495 | ((bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) && | ||
2496 | (fs_info->avail_metadata_alloc_bits & allowed) && | ||
2497 | !(bctl->meta.target & allowed))) { | ||
2498 | if (bctl->flags & BTRFS_BALANCE_FORCE) { | ||
2499 | printk(KERN_INFO "btrfs: force reducing metadata " | ||
2500 | "integrity\n"); | ||
2501 | } else { | ||
2502 | printk(KERN_ERR "btrfs: balance will reduce metadata " | ||
2503 | "integrity, use force if you want this\n"); | ||
2504 | ret = -EINVAL; | ||
2505 | goto out; | ||
2506 | } | ||
2507 | } | ||
2508 | |||
2509 | do_balance: | ||
2441 | set_balance_control(bctl); | 2510 | set_balance_control(bctl); |
2442 | 2511 | ||
2443 | mutex_unlock(&fs_info->balance_mutex); | 2512 | mutex_unlock(&fs_info->balance_mutex); |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index eac26c359312..79ee9c324562 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -196,6 +196,9 @@ struct map_lookup { | |||
196 | #define BTRFS_BALANCE_TYPE_MASK (BTRFS_BALANCE_DATA | \ | 196 | #define BTRFS_BALANCE_TYPE_MASK (BTRFS_BALANCE_DATA | \ |
197 | BTRFS_BALANCE_SYSTEM | \ | 197 | BTRFS_BALANCE_SYSTEM | \ |
198 | BTRFS_BALANCE_METADATA) | 198 | BTRFS_BALANCE_METADATA) |
199 | |||
200 | #define BTRFS_BALANCE_FORCE (1ULL << 3) | ||
201 | |||
199 | /* | 202 | /* |
200 | * Balance filters | 203 | * Balance filters |
201 | */ | 204 | */ |
@@ -205,6 +208,8 @@ struct map_lookup { | |||
205 | #define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3) | 208 | #define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3) |
206 | #define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4) | 209 | #define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4) |
207 | 210 | ||
211 | #define BTRFS_BALANCE_ARGS_CONVERT (1ULL << 8) | ||
212 | |||
208 | struct btrfs_balance_args; | 213 | struct btrfs_balance_args; |
209 | struct btrfs_balance_control { | 214 | struct btrfs_balance_control { |
210 | struct btrfs_fs_info *fs_info; | 215 | struct btrfs_fs_info *fs_info; |