aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2012-01-16 15:04:49 -0500
committerIlya Dryomov <idryomov@gmail.com>2012-01-16 15:04:49 -0500
commit19a39dce3b9bf0244d19a446718ad6f7605ff099 (patch)
tree4834e177b8b64405aa858bfdcfbabd890277102b /fs/btrfs
parentde322263d3a6d4ffd4ed7c4d0c6536e9497aec9b (diff)
Btrfs: add balance progress reporting
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ioctl.c45
-rw-r--r--fs/btrfs/ioctl.h2
-rw-r--r--fs/btrfs/volumes.c39
-rw-r--r--fs/btrfs/volumes.h3
4 files changed, 84 insertions, 5 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 85e546ffe3c7..1e7a9bac31ab 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3065,7 +3065,7 @@ out:
3065 return ret; 3065 return ret;
3066} 3066}
3067 3067
3068void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, 3068void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
3069 struct btrfs_ioctl_balance_args *bargs) 3069 struct btrfs_ioctl_balance_args *bargs)
3070{ 3070{
3071 struct btrfs_balance_control *bctl = fs_info->balance_ctl; 3071 struct btrfs_balance_control *bctl = fs_info->balance_ctl;
@@ -3082,6 +3082,14 @@ void update_ioctl_balance_args(struct btrfs_fs_info *fs_info,
3082 memcpy(&bargs->data, &bctl->data, sizeof(bargs->data)); 3082 memcpy(&bargs->data, &bctl->data, sizeof(bargs->data));
3083 memcpy(&bargs->meta, &bctl->meta, sizeof(bargs->meta)); 3083 memcpy(&bargs->meta, &bctl->meta, sizeof(bargs->meta));
3084 memcpy(&bargs->sys, &bctl->sys, sizeof(bargs->sys)); 3084 memcpy(&bargs->sys, &bctl->sys, sizeof(bargs->sys));
3085
3086 if (lock) {
3087 spin_lock(&fs_info->balance_lock);
3088 memcpy(&bargs->stat, &bctl->stat, sizeof(bargs->stat));
3089 spin_unlock(&fs_info->balance_lock);
3090 } else {
3091 memcpy(&bargs->stat, &bctl->stat, sizeof(bargs->stat));
3092 }
3085} 3093}
3086 3094
3087static long btrfs_ioctl_balance(struct btrfs_root *root, void __user *arg) 3095static long btrfs_ioctl_balance(struct btrfs_root *root, void __user *arg)
@@ -3181,6 +3189,39 @@ static long btrfs_ioctl_balance_ctl(struct btrfs_root *root, int cmd)
3181 return -EINVAL; 3189 return -EINVAL;
3182} 3190}
3183 3191
3192static long btrfs_ioctl_balance_progress(struct btrfs_root *root,
3193 void __user *arg)
3194{
3195 struct btrfs_fs_info *fs_info = root->fs_info;
3196 struct btrfs_ioctl_balance_args *bargs;
3197 int ret = 0;
3198
3199 if (!capable(CAP_SYS_ADMIN))
3200 return -EPERM;
3201
3202 mutex_lock(&fs_info->balance_mutex);
3203 if (!fs_info->balance_ctl) {
3204 ret = -ENOTCONN;
3205 goto out;
3206 }
3207
3208 bargs = kzalloc(sizeof(*bargs), GFP_NOFS);
3209 if (!bargs) {
3210 ret = -ENOMEM;
3211 goto out;
3212 }
3213
3214 update_ioctl_balance_args(fs_info, 1, bargs);
3215
3216 if (copy_to_user(arg, bargs, sizeof(*bargs)))
3217 ret = -EFAULT;
3218
3219 kfree(bargs);
3220out:
3221 mutex_unlock(&fs_info->balance_mutex);
3222 return ret;
3223}
3224
3184long btrfs_ioctl(struct file *file, unsigned int 3225long btrfs_ioctl(struct file *file, unsigned int
3185 cmd, unsigned long arg) 3226 cmd, unsigned long arg)
3186{ 3227{
@@ -3261,6 +3302,8 @@ long btrfs_ioctl(struct file *file, unsigned int
3261 return btrfs_ioctl_balance(root, argp); 3302 return btrfs_ioctl_balance(root, argp);
3262 case BTRFS_IOC_BALANCE_CTL: 3303 case BTRFS_IOC_BALANCE_CTL:
3263 return btrfs_ioctl_balance_ctl(root, arg); 3304 return btrfs_ioctl_balance_ctl(root, arg);
3305 case BTRFS_IOC_BALANCE_PROGRESS:
3306 return btrfs_ioctl_balance_progress(root, argp);
3264 } 3307 }
3265 3308
3266 return -ENOTTY; 3309 return -ENOTTY;
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
index cd19d10794b9..4f69028a68c4 100644
--- a/fs/btrfs/ioctl.h
+++ b/fs/btrfs/ioctl.h
@@ -324,6 +324,8 @@ struct btrfs_ioctl_logical_ino_args {
324#define BTRFS_IOC_BALANCE_V2 _IOWR(BTRFS_IOCTL_MAGIC, 32, \ 324#define BTRFS_IOC_BALANCE_V2 _IOWR(BTRFS_IOCTL_MAGIC, 32, \
325 struct btrfs_ioctl_balance_args) 325 struct btrfs_ioctl_balance_args)
326#define BTRFS_IOC_BALANCE_CTL _IOW(BTRFS_IOCTL_MAGIC, 33, int) 326#define BTRFS_IOC_BALANCE_CTL _IOW(BTRFS_IOCTL_MAGIC, 33, int)
327#define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 34, \
328 struct btrfs_ioctl_balance_args)
327#define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \ 329#define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \
328 struct btrfs_ioctl_ino_path_args) 330 struct btrfs_ioctl_ino_path_args)
329#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \ 331#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index c32667318ae4..d73439b4d7da 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2441,6 +2441,7 @@ static u64 div_factor(u64 num, int factor)
2441 2441
2442static int __btrfs_balance(struct btrfs_fs_info *fs_info) 2442static int __btrfs_balance(struct btrfs_fs_info *fs_info)
2443{ 2443{
2444 struct btrfs_balance_control *bctl = fs_info->balance_ctl;
2444 struct btrfs_root *chunk_root = fs_info->chunk_root; 2445 struct btrfs_root *chunk_root = fs_info->chunk_root;
2445 struct btrfs_root *dev_root = fs_info->dev_root; 2446 struct btrfs_root *dev_root = fs_info->dev_root;
2446 struct list_head *devices; 2447 struct list_head *devices;
@@ -2456,6 +2457,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
2456 int slot; 2457 int slot;
2457 int ret; 2458 int ret;
2458 int enospc_errors = 0; 2459 int enospc_errors = 0;
2460 bool counting = true;
2459 2461
2460 /* step one make some room on all the devices */ 2462 /* step one make some room on all the devices */
2461 devices = &fs_info->fs_devices->devices; 2463 devices = &fs_info->fs_devices->devices;
@@ -2487,12 +2489,18 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
2487 ret = -ENOMEM; 2489 ret = -ENOMEM;
2488 goto error; 2490 goto error;
2489 } 2491 }
2492
2493 /* zero out stat counters */
2494 spin_lock(&fs_info->balance_lock);
2495 memset(&bctl->stat, 0, sizeof(bctl->stat));
2496 spin_unlock(&fs_info->balance_lock);
2497again:
2490 key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; 2498 key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
2491 key.offset = (u64)-1; 2499 key.offset = (u64)-1;
2492 key.type = BTRFS_CHUNK_ITEM_KEY; 2500 key.type = BTRFS_CHUNK_ITEM_KEY;
2493 2501
2494 while (1) { 2502 while (1) {
2495 if (atomic_read(&fs_info->balance_pause_req) || 2503 if ((!counting && atomic_read(&fs_info->balance_pause_req)) ||
2496 atomic_read(&fs_info->balance_cancel_req)) { 2504 atomic_read(&fs_info->balance_cancel_req)) {
2497 ret = -ECANCELED; 2505 ret = -ECANCELED;
2498 goto error; 2506 goto error;
@@ -2529,24 +2537,47 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
2529 2537
2530 chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); 2538 chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
2531 2539
2540 if (!counting) {
2541 spin_lock(&fs_info->balance_lock);
2542 bctl->stat.considered++;
2543 spin_unlock(&fs_info->balance_lock);
2544 }
2545
2532 ret = should_balance_chunk(chunk_root, leaf, chunk, 2546 ret = should_balance_chunk(chunk_root, leaf, chunk,
2533 found_key.offset); 2547 found_key.offset);
2534 btrfs_release_path(path); 2548 btrfs_release_path(path);
2535 if (!ret) 2549 if (!ret)
2536 goto loop; 2550 goto loop;
2537 2551
2552 if (counting) {
2553 spin_lock(&fs_info->balance_lock);
2554 bctl->stat.expected++;
2555 spin_unlock(&fs_info->balance_lock);
2556 goto loop;
2557 }
2558
2538 ret = btrfs_relocate_chunk(chunk_root, 2559 ret = btrfs_relocate_chunk(chunk_root,
2539 chunk_root->root_key.objectid, 2560 chunk_root->root_key.objectid,
2540 found_key.objectid, 2561 found_key.objectid,
2541 found_key.offset); 2562 found_key.offset);
2542 if (ret && ret != -ENOSPC) 2563 if (ret && ret != -ENOSPC)
2543 goto error; 2564 goto error;
2544 if (ret == -ENOSPC) 2565 if (ret == -ENOSPC) {
2545 enospc_errors++; 2566 enospc_errors++;
2567 } else {
2568 spin_lock(&fs_info->balance_lock);
2569 bctl->stat.completed++;
2570 spin_unlock(&fs_info->balance_lock);
2571 }
2546loop: 2572loop:
2547 key.offset = found_key.offset - 1; 2573 key.offset = found_key.offset - 1;
2548 } 2574 }
2549 2575
2576 if (counting) {
2577 btrfs_release_path(path);
2578 counting = false;
2579 goto again;
2580 }
2550error: 2581error:
2551 btrfs_free_path(path); 2582 btrfs_free_path(path);
2552 if (enospc_errors) { 2583 if (enospc_errors) {
@@ -2576,7 +2607,7 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info)
2576 BUG_ON(ret); 2607 BUG_ON(ret);
2577} 2608}
2578 2609
2579void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, 2610void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
2580 struct btrfs_ioctl_balance_args *bargs); 2611 struct btrfs_ioctl_balance_args *bargs);
2581 2612
2582/* 2613/*
@@ -2706,7 +2737,7 @@ do_balance:
2706 2737
2707 if (bargs) { 2738 if (bargs) {
2708 memset(bargs, 0, sizeof(*bargs)); 2739 memset(bargs, 0, sizeof(*bargs));
2709 update_ioctl_balance_args(fs_info, bargs); 2740 update_ioctl_balance_args(fs_info, 0, bargs);
2710 } 2741 }
2711 2742
2712 if ((ret && ret != -ECANCELED && ret != -ENOSPC) || 2743 if ((ret && ret != -ECANCELED && ret != -ENOSPC) ||
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index caa9abd218ef..6faec9dd1f93 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -218,6 +218,7 @@ struct map_lookup {
218#define BTRFS_BALANCE_ARGS_SOFT (1ULL << 9) 218#define BTRFS_BALANCE_ARGS_SOFT (1ULL << 9)
219 219
220struct btrfs_balance_args; 220struct btrfs_balance_args;
221struct btrfs_balance_progress;
221struct btrfs_balance_control { 222struct btrfs_balance_control {
222 struct btrfs_fs_info *fs_info; 223 struct btrfs_fs_info *fs_info;
223 224
@@ -226,6 +227,8 @@ struct btrfs_balance_control {
226 struct btrfs_balance_args sys; 227 struct btrfs_balance_args sys;
227 228
228 u64 flags; 229 u64 flags;
230
231 struct btrfs_balance_progress stat;
229}; 232};
230 233
231int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start, 234int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start,