Skip to content

Commit

Permalink
Btrfs: allow for canceling restriper
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
idryomov committed Jan 16, 2012
1 parent 837d5b6 commit a7e99c6
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 3 deletions.
1 change: 1 addition & 0 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,7 @@ struct btrfs_fs_info {
struct mutex balance_mutex;
atomic_t balance_running;
atomic_t balance_pause_req;
atomic_t balance_cancel_req;
struct btrfs_balance_control *balance_ctl;
wait_queue_head_t balance_wait_q;

Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2006,6 +2006,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
mutex_init(&fs_info->balance_mutex);
atomic_set(&fs_info->balance_running, 0);
atomic_set(&fs_info->balance_pause_req, 0);
atomic_set(&fs_info->balance_cancel_req, 0);
fs_info->balance_ctl = NULL;
init_waitqueue_head(&fs_info->balance_wait_q);

Expand Down
4 changes: 4 additions & 0 deletions fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -3076,6 +3076,8 @@ void update_ioctl_balance_args(struct btrfs_fs_info *fs_info,
bargs->state |= BTRFS_BALANCE_STATE_RUNNING;
if (atomic_read(&fs_info->balance_pause_req))
bargs->state |= BTRFS_BALANCE_STATE_PAUSE_REQ;
if (atomic_read(&fs_info->balance_cancel_req))
bargs->state |= BTRFS_BALANCE_STATE_CANCEL_REQ;

memcpy(&bargs->data, &bctl->data, sizeof(bargs->data));
memcpy(&bargs->meta, &bctl->meta, sizeof(bargs->meta));
Expand Down Expand Up @@ -3157,6 +3159,8 @@ static long btrfs_ioctl_balance_ctl(struct btrfs_root *root, int cmd)
switch (cmd) {
case BTRFS_BALANCE_CTL_PAUSE:
return btrfs_pause_balance(root->fs_info);
case BTRFS_BALANCE_CTL_CANCEL:
return btrfs_cancel_balance(root->fs_info);
}

return -EINVAL;
Expand Down
2 changes: 2 additions & 0 deletions fs/btrfs/ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ struct btrfs_ioctl_fs_info_args {

/* balance control ioctl modes */
#define BTRFS_BALANCE_CTL_PAUSE 1
#define BTRFS_BALANCE_CTL_CANCEL 2

/*
* this is packed, because it should be exactly the same as its disk
Expand Down Expand Up @@ -142,6 +143,7 @@ struct btrfs_balance_progress {

#define BTRFS_BALANCE_STATE_RUNNING (1ULL << 0)
#define BTRFS_BALANCE_STATE_PAUSE_REQ (1ULL << 1)
#define BTRFS_BALANCE_STATE_CANCEL_REQ (1ULL << 2)

struct btrfs_ioctl_balance_args {
__u64 flags; /* in/out */
Expand Down
47 changes: 44 additions & 3 deletions fs/btrfs/volumes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2492,7 +2492,8 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
key.type = BTRFS_CHUNK_ITEM_KEY;

while (1) {
if (atomic_read(&fs_info->balance_pause_req)) {
if (atomic_read(&fs_info->balance_pause_req) ||
atomic_read(&fs_info->balance_cancel_req)) {
ret = -ECANCELED;
goto error;
}
Expand Down Expand Up @@ -2560,7 +2561,10 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)

static inline int balance_need_close(struct btrfs_fs_info *fs_info)
{
return atomic_read(&fs_info->balance_pause_req) == 0;
/* cancel requested || normal exit path */
return atomic_read(&fs_info->balance_cancel_req) ||
(atomic_read(&fs_info->balance_pause_req) == 0 &&
atomic_read(&fs_info->balance_cancel_req) == 0);
}

static void __cancel_balance(struct btrfs_fs_info *fs_info)
Expand All @@ -2586,7 +2590,8 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
int ret;

if (btrfs_fs_closing(fs_info) ||
atomic_read(&fs_info->balance_pause_req)) {
atomic_read(&fs_info->balance_pause_req) ||
atomic_read(&fs_info->balance_cancel_req)) {
ret = -EINVAL;
goto out;
}
Expand Down Expand Up @@ -2832,6 +2837,42 @@ int btrfs_pause_balance(struct btrfs_fs_info *fs_info)
return ret;
}

int btrfs_cancel_balance(struct btrfs_fs_info *fs_info)
{
mutex_lock(&fs_info->balance_mutex);
if (!fs_info->balance_ctl) {
mutex_unlock(&fs_info->balance_mutex);
return -ENOTCONN;
}

atomic_inc(&fs_info->balance_cancel_req);
/*
* if we are running just wait and return, balance item is
* deleted in btrfs_balance in this case
*/
if (atomic_read(&fs_info->balance_running)) {
mutex_unlock(&fs_info->balance_mutex);
wait_event(fs_info->balance_wait_q,
atomic_read(&fs_info->balance_running) == 0);
mutex_lock(&fs_info->balance_mutex);
} else {
/* __cancel_balance needs volume_mutex */
mutex_unlock(&fs_info->balance_mutex);
mutex_lock(&fs_info->volume_mutex);
mutex_lock(&fs_info->balance_mutex);

if (fs_info->balance_ctl)
__cancel_balance(fs_info);

mutex_unlock(&fs_info->volume_mutex);
}

BUG_ON(fs_info->balance_ctl || atomic_read(&fs_info->balance_running));
atomic_dec(&fs_info->balance_cancel_req);
mutex_unlock(&fs_info->balance_mutex);
return 0;
}

/*
* shrinking a device means finding all of the device extents past
* the new size, and then following the back refs to the chunks.
Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/volumes.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
struct btrfs_ioctl_balance_args *bargs);
int btrfs_recover_balance(struct btrfs_root *tree_root);
int btrfs_pause_balance(struct btrfs_fs_info *fs_info);
int btrfs_cancel_balance(struct btrfs_fs_info *fs_info);
int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset);
int find_free_dev_extent(struct btrfs_trans_handle *trans,
struct btrfs_device *device, u64 num_bytes,
Expand Down

0 comments on commit a7e99c6

Please sign in to comment.