Btrfs: save balance parameters to disk
Introduce a new btree objectid for storing balance item. The reason is to be able to resume restriper after a crash with the same parameters. Balance item has a very high objectid and goes into tree of tree roots. The key for the new item is as follows: [ BTRFS_BALANCE_OBJECTID ; BTRFS_BALANCE_ITEM_KEY ; 0 ] Older kernels simply ignore it so it's safe to mount with an older kernel and then go back to the newer one. Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
@@ -2073,6 +2073,97 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int insert_balance_item(struct btrfs_root *root,
|
||||
struct btrfs_balance_control *bctl)
|
||||
{
|
||||
struct btrfs_trans_handle *trans;
|
||||
struct btrfs_balance_item *item;
|
||||
struct btrfs_disk_balance_args disk_bargs;
|
||||
struct btrfs_path *path;
|
||||
struct extent_buffer *leaf;
|
||||
struct btrfs_key key;
|
||||
int ret, err;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path)
|
||||
return -ENOMEM;
|
||||
|
||||
trans = btrfs_start_transaction(root, 0);
|
||||
if (IS_ERR(trans)) {
|
||||
btrfs_free_path(path);
|
||||
return PTR_ERR(trans);
|
||||
}
|
||||
|
||||
key.objectid = BTRFS_BALANCE_OBJECTID;
|
||||
key.type = BTRFS_BALANCE_ITEM_KEY;
|
||||
key.offset = 0;
|
||||
|
||||
ret = btrfs_insert_empty_item(trans, root, path, &key,
|
||||
sizeof(*item));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
leaf = path->nodes[0];
|
||||
item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_balance_item);
|
||||
|
||||
memset_extent_buffer(leaf, 0, (unsigned long)item, sizeof(*item));
|
||||
|
||||
btrfs_cpu_balance_args_to_disk(&disk_bargs, &bctl->data);
|
||||
btrfs_set_balance_data(leaf, item, &disk_bargs);
|
||||
btrfs_cpu_balance_args_to_disk(&disk_bargs, &bctl->meta);
|
||||
btrfs_set_balance_meta(leaf, item, &disk_bargs);
|
||||
btrfs_cpu_balance_args_to_disk(&disk_bargs, &bctl->sys);
|
||||
btrfs_set_balance_sys(leaf, item, &disk_bargs);
|
||||
|
||||
btrfs_set_balance_flags(leaf, item, bctl->flags);
|
||||
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
out:
|
||||
btrfs_free_path(path);
|
||||
err = btrfs_commit_transaction(trans, root);
|
||||
if (err && !ret)
|
||||
ret = err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int del_balance_item(struct btrfs_root *root)
|
||||
{
|
||||
struct btrfs_trans_handle *trans;
|
||||
struct btrfs_path *path;
|
||||
struct btrfs_key key;
|
||||
int ret, err;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path)
|
||||
return -ENOMEM;
|
||||
|
||||
trans = btrfs_start_transaction(root, 0);
|
||||
if (IS_ERR(trans)) {
|
||||
btrfs_free_path(path);
|
||||
return PTR_ERR(trans);
|
||||
}
|
||||
|
||||
key.objectid = BTRFS_BALANCE_OBJECTID;
|
||||
key.type = BTRFS_BALANCE_ITEM_KEY;
|
||||
key.offset = 0;
|
||||
|
||||
ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (ret > 0) {
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = btrfs_del_item(trans, root, path);
|
||||
out:
|
||||
btrfs_free_path(path);
|
||||
err = btrfs_commit_transaction(trans, root);
|
||||
if (err && !ret)
|
||||
ret = err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Should be called with both balance and volume mutexes held to
|
||||
* serialize other volume operations (add_dev/rm_dev/resize) with
|
||||
@@ -2423,7 +2514,11 @@ error:
|
||||
|
||||
static void __cancel_balance(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
unset_balance_control(fs_info);
|
||||
ret = del_balance_item(fs_info->tree_root);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
void update_ioctl_balance_args(struct btrfs_fs_info *fs_info,
|
||||
@@ -2530,6 +2625,10 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
|
||||
}
|
||||
|
||||
do_balance:
|
||||
ret = insert_balance_item(fs_info->tree_root, bctl);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
set_balance_control(bctl);
|
||||
|
||||
mutex_unlock(&fs_info->balance_mutex);
|
||||
|
Reference in New Issue
Block a user