diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2012-01-16 15:04:49 -0500 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2012-01-16 15:04:49 -0500 |
commit | a7e99c691af553fc15ac46a51f130b7c59a65f76 (patch) | |
tree | 55491f285683951d509819a66e614ac6f12659dd /fs | |
parent | 837d5b6e46d1a4af5b6cc8f2fe83cb5de79a2961 (diff) |
Btrfs: allow for canceling restriper
Implement an ioctl for canceling restriper. Currently we wait until
relocation of the current block group is finished, in future this can be
done by triggering a commit. Balance item is deleted and no memory
about the interrupted balance is kept.
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 1 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 4 | ||||
-rw-r--r-- | fs/btrfs/ioctl.h | 2 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 47 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 1 |
6 files changed, 53 insertions, 3 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 1afda75d5414..dfc136cc07d7 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1216,6 +1216,7 @@ struct btrfs_fs_info { | |||
1216 | struct mutex balance_mutex; | 1216 | struct mutex balance_mutex; |
1217 | atomic_t balance_running; | 1217 | atomic_t balance_running; |
1218 | atomic_t balance_pause_req; | 1218 | atomic_t balance_pause_req; |
1219 | atomic_t balance_cancel_req; | ||
1219 | struct btrfs_balance_control *balance_ctl; | 1220 | struct btrfs_balance_control *balance_ctl; |
1220 | wait_queue_head_t balance_wait_q; | 1221 | wait_queue_head_t balance_wait_q; |
1221 | 1222 | ||
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 8ce837407800..c23b82d8ec08 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -2006,6 +2006,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
2006 | mutex_init(&fs_info->balance_mutex); | 2006 | mutex_init(&fs_info->balance_mutex); |
2007 | atomic_set(&fs_info->balance_running, 0); | 2007 | atomic_set(&fs_info->balance_running, 0); |
2008 | atomic_set(&fs_info->balance_pause_req, 0); | 2008 | atomic_set(&fs_info->balance_pause_req, 0); |
2009 | atomic_set(&fs_info->balance_cancel_req, 0); | ||
2009 | fs_info->balance_ctl = NULL; | 2010 | fs_info->balance_ctl = NULL; |
2010 | init_waitqueue_head(&fs_info->balance_wait_q); | 2011 | init_waitqueue_head(&fs_info->balance_wait_q); |
2011 | 2012 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index f572c53dda4f..60852217ce9a 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -3076,6 +3076,8 @@ void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, | |||
3076 | bargs->state |= BTRFS_BALANCE_STATE_RUNNING; | 3076 | bargs->state |= BTRFS_BALANCE_STATE_RUNNING; |
3077 | if (atomic_read(&fs_info->balance_pause_req)) | 3077 | if (atomic_read(&fs_info->balance_pause_req)) |
3078 | bargs->state |= BTRFS_BALANCE_STATE_PAUSE_REQ; | 3078 | bargs->state |= BTRFS_BALANCE_STATE_PAUSE_REQ; |
3079 | if (atomic_read(&fs_info->balance_cancel_req)) | ||
3080 | bargs->state |= BTRFS_BALANCE_STATE_CANCEL_REQ; | ||
3079 | 3081 | ||
3080 | memcpy(&bargs->data, &bctl->data, sizeof(bargs->data)); | 3082 | memcpy(&bargs->data, &bctl->data, sizeof(bargs->data)); |
3081 | memcpy(&bargs->meta, &bctl->meta, sizeof(bargs->meta)); | 3083 | memcpy(&bargs->meta, &bctl->meta, sizeof(bargs->meta)); |
@@ -3157,6 +3159,8 @@ static long btrfs_ioctl_balance_ctl(struct btrfs_root *root, int cmd) | |||
3157 | switch (cmd) { | 3159 | switch (cmd) { |
3158 | case BTRFS_BALANCE_CTL_PAUSE: | 3160 | case BTRFS_BALANCE_CTL_PAUSE: |
3159 | return btrfs_pause_balance(root->fs_info); | 3161 | return btrfs_pause_balance(root->fs_info); |
3162 | case BTRFS_BALANCE_CTL_CANCEL: | ||
3163 | return btrfs_cancel_balance(root->fs_info); | ||
3160 | } | 3164 | } |
3161 | 3165 | ||
3162 | return -EINVAL; | 3166 | return -EINVAL; |
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index e972e11a8d77..cd19d10794b9 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h | |||
@@ -111,6 +111,7 @@ struct btrfs_ioctl_fs_info_args { | |||
111 | 111 | ||
112 | /* balance control ioctl modes */ | 112 | /* balance control ioctl modes */ |
113 | #define BTRFS_BALANCE_CTL_PAUSE 1 | 113 | #define BTRFS_BALANCE_CTL_PAUSE 1 |
114 | #define BTRFS_BALANCE_CTL_CANCEL 2 | ||
114 | 115 | ||
115 | /* | 116 | /* |
116 | * this is packed, because it should be exactly the same as its disk | 117 | * this is packed, because it should be exactly the same as its disk |
@@ -142,6 +143,7 @@ struct btrfs_balance_progress { | |||
142 | 143 | ||
143 | #define BTRFS_BALANCE_STATE_RUNNING (1ULL << 0) | 144 | #define BTRFS_BALANCE_STATE_RUNNING (1ULL << 0) |
144 | #define BTRFS_BALANCE_STATE_PAUSE_REQ (1ULL << 1) | 145 | #define BTRFS_BALANCE_STATE_PAUSE_REQ (1ULL << 1) |
146 | #define BTRFS_BALANCE_STATE_CANCEL_REQ (1ULL << 2) | ||
145 | 147 | ||
146 | struct btrfs_ioctl_balance_args { | 148 | struct btrfs_ioctl_balance_args { |
147 | __u64 flags; /* in/out */ | 149 | __u64 flags; /* in/out */ |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index d32660ce753d..c32667318ae4 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -2492,7 +2492,8 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info) | |||
2492 | key.type = BTRFS_CHUNK_ITEM_KEY; | 2492 | key.type = BTRFS_CHUNK_ITEM_KEY; |
2493 | 2493 | ||
2494 | while (1) { | 2494 | while (1) { |
2495 | if (atomic_read(&fs_info->balance_pause_req)) { | 2495 | if (atomic_read(&fs_info->balance_pause_req) || |
2496 | atomic_read(&fs_info->balance_cancel_req)) { | ||
2496 | ret = -ECANCELED; | 2497 | ret = -ECANCELED; |
2497 | goto error; | 2498 | goto error; |
2498 | } | 2499 | } |
@@ -2560,7 +2561,10 @@ error: | |||
2560 | 2561 | ||
2561 | static inline int balance_need_close(struct btrfs_fs_info *fs_info) | 2562 | static inline int balance_need_close(struct btrfs_fs_info *fs_info) |
2562 | { | 2563 | { |
2563 | return atomic_read(&fs_info->balance_pause_req) == 0; | 2564 | /* cancel requested || normal exit path */ |
2565 | return atomic_read(&fs_info->balance_cancel_req) || | ||
2566 | (atomic_read(&fs_info->balance_pause_req) == 0 && | ||
2567 | atomic_read(&fs_info->balance_cancel_req) == 0); | ||
2564 | } | 2568 | } |
2565 | 2569 | ||
2566 | static void __cancel_balance(struct btrfs_fs_info *fs_info) | 2570 | static void __cancel_balance(struct btrfs_fs_info *fs_info) |
@@ -2586,7 +2590,8 @@ int btrfs_balance(struct btrfs_balance_control *bctl, | |||
2586 | int ret; | 2590 | int ret; |
2587 | 2591 | ||
2588 | if (btrfs_fs_closing(fs_info) || | 2592 | if (btrfs_fs_closing(fs_info) || |
2589 | atomic_read(&fs_info->balance_pause_req)) { | 2593 | atomic_read(&fs_info->balance_pause_req) || |
2594 | atomic_read(&fs_info->balance_cancel_req)) { | ||
2590 | ret = -EINVAL; | 2595 | ret = -EINVAL; |
2591 | goto out; | 2596 | goto out; |
2592 | } | 2597 | } |
@@ -2832,6 +2837,42 @@ int btrfs_pause_balance(struct btrfs_fs_info *fs_info) | |||
2832 | return ret; | 2837 | return ret; |
2833 | } | 2838 | } |
2834 | 2839 | ||
2840 | int btrfs_cancel_balance(struct btrfs_fs_info *fs_info) | ||
2841 | { | ||
2842 | mutex_lock(&fs_info->balance_mutex); | ||
2843 | if (!fs_info->balance_ctl) { | ||
2844 | mutex_unlock(&fs_info->balance_mutex); | ||
2845 | return -ENOTCONN; | ||
2846 | } | ||
2847 | |||
2848 | atomic_inc(&fs_info->balance_cancel_req); | ||
2849 | /* | ||
2850 | * if we are running just wait and return, balance item is | ||
2851 | * deleted in btrfs_balance in this case | ||
2852 | */ | ||
2853 | if (atomic_read(&fs_info->balance_running)) { | ||
2854 | mutex_unlock(&fs_info->balance_mutex); | ||
2855 | wait_event(fs_info->balance_wait_q, | ||
2856 | atomic_read(&fs_info->balance_running) == 0); | ||
2857 | mutex_lock(&fs_info->balance_mutex); | ||
2858 | } else { | ||
2859 | /* __cancel_balance needs volume_mutex */ | ||
2860 | mutex_unlock(&fs_info->balance_mutex); | ||
2861 | mutex_lock(&fs_info->volume_mutex); | ||
2862 | mutex_lock(&fs_info->balance_mutex); | ||
2863 | |||
2864 | if (fs_info->balance_ctl) | ||
2865 | __cancel_balance(fs_info); | ||
2866 | |||
2867 | mutex_unlock(&fs_info->volume_mutex); | ||
2868 | } | ||
2869 | |||
2870 | BUG_ON(fs_info->balance_ctl || atomic_read(&fs_info->balance_running)); | ||
2871 | atomic_dec(&fs_info->balance_cancel_req); | ||
2872 | mutex_unlock(&fs_info->balance_mutex); | ||
2873 | return 0; | ||
2874 | } | ||
2875 | |||
2835 | /* | 2876 | /* |
2836 | * shrinking a device means finding all of the device extents past | 2877 | * shrinking a device means finding all of the device extents past |
2837 | * the new size, and then following the back refs to the chunks. | 2878 | * the new size, and then following the back refs to the chunks. |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 80953afb12b9..caa9abd218ef 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -274,6 +274,7 @@ int btrfs_balance(struct btrfs_balance_control *bctl, | |||
274 | struct btrfs_ioctl_balance_args *bargs); | 274 | struct btrfs_ioctl_balance_args *bargs); |
275 | int btrfs_recover_balance(struct btrfs_root *tree_root); | 275 | int btrfs_recover_balance(struct btrfs_root *tree_root); |
276 | int btrfs_pause_balance(struct btrfs_fs_info *fs_info); | 276 | int btrfs_pause_balance(struct btrfs_fs_info *fs_info); |
277 | int btrfs_cancel_balance(struct btrfs_fs_info *fs_info); | ||
277 | int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset); | 278 | int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset); |
278 | int find_free_dev_extent(struct btrfs_trans_handle *trans, | 279 | int find_free_dev_extent(struct btrfs_trans_handle *trans, |
279 | struct btrfs_device *device, u64 num_bytes, | 280 | struct btrfs_device *device, u64 num_bytes, |