aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2012-01-16 15:04:48 -0500
committerIlya Dryomov <idryomov@gmail.com>2012-01-16 15:04:48 -0500
commite4d8ec0f65b91bfb4984a4927632ded95f9825ad (patch)
tree4727c977803093ec5cdf93da4fcab34cc8de8ecf /fs/btrfs
parent70922617b0099f420deceb53d5dc7f4fb30d08d0 (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.c56
-rw-r--r--fs/btrfs/volumes.c69
-rw-r--r--fs/btrfs/volumes.h5
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 */
3035u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) 3037u64 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
3098out:
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
2509do_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
208struct btrfs_balance_args; 213struct btrfs_balance_args;
209struct btrfs_balance_control { 214struct btrfs_balance_control {
210 struct btrfs_fs_info *fs_info; 215 struct btrfs_fs_info *fs_info;