diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2012-06-22 14:24:12 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2012-07-02 15:39:16 -0400 |
commit | 68310a5e42f93c2242ec1836c3b18d531e0065e2 (patch) | |
tree | cf457369274a1633ba02170fcb6aab0114906f0a /fs/btrfs | |
parent | c3473e830074ef04f974f2829690942dd8580619 (diff) |
Btrfs: restore restriper state on all mounts
Fix a bug that triggered asserts in btrfs_balance() in both normal and
resume modes -- restriper state was not properly restored on read-only
mounts. This factors out resuming code from btrfs_restore_balance(),
which is now also called earlier in the mount sequence to avoid the
problem of some early writes getting the old profile.
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/disk-io.c | 10 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 39 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 2 |
3 files changed, 26 insertions, 25 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 7d7bc8eace86..3a7961ba161e 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -2354,12 +2354,17 @@ retry_root_backup: | |||
2354 | BTRFS_CSUM_TREE_OBJECTID, csum_root); | 2354 | BTRFS_CSUM_TREE_OBJECTID, csum_root); |
2355 | if (ret) | 2355 | if (ret) |
2356 | goto recovery_tree_root; | 2356 | goto recovery_tree_root; |
2357 | |||
2358 | csum_root->track_dirty = 1; | 2357 | csum_root->track_dirty = 1; |
2359 | 2358 | ||
2360 | fs_info->generation = generation; | 2359 | fs_info->generation = generation; |
2361 | fs_info->last_trans_committed = generation; | 2360 | fs_info->last_trans_committed = generation; |
2362 | 2361 | ||
2362 | ret = btrfs_recover_balance(fs_info); | ||
2363 | if (ret) { | ||
2364 | printk(KERN_WARNING "btrfs: failed to recover balance\n"); | ||
2365 | goto fail_block_groups; | ||
2366 | } | ||
2367 | |||
2363 | ret = btrfs_init_dev_stats(fs_info); | 2368 | ret = btrfs_init_dev_stats(fs_info); |
2364 | if (ret) { | 2369 | if (ret) { |
2365 | printk(KERN_ERR "btrfs: failed to init dev_stats: %d\n", | 2370 | printk(KERN_ERR "btrfs: failed to init dev_stats: %d\n", |
@@ -2492,9 +2497,6 @@ retry_root_backup: | |||
2492 | err = btrfs_orphan_cleanup(fs_info->tree_root); | 2497 | err = btrfs_orphan_cleanup(fs_info->tree_root); |
2493 | up_read(&fs_info->cleanup_work_sem); | 2498 | up_read(&fs_info->cleanup_work_sem); |
2494 | 2499 | ||
2495 | if (!err) | ||
2496 | err = btrfs_recover_balance(fs_info->tree_root); | ||
2497 | |||
2498 | if (err) { | 2500 | if (err) { |
2499 | close_ctree(tree_root); | 2501 | close_ctree(tree_root); |
2500 | return err; | 2502 | return err; |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 3f292cf693a7..48943d0f861a 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -2867,9 +2867,8 @@ static int balance_kthread(void *data) | |||
2867 | return ret; | 2867 | return ret; |
2868 | } | 2868 | } |
2869 | 2869 | ||
2870 | int btrfs_recover_balance(struct btrfs_root *tree_root) | 2870 | int btrfs_recover_balance(struct btrfs_fs_info *fs_info) |
2871 | { | 2871 | { |
2872 | struct task_struct *tsk; | ||
2873 | struct btrfs_balance_control *bctl; | 2872 | struct btrfs_balance_control *bctl; |
2874 | struct btrfs_balance_item *item; | 2873 | struct btrfs_balance_item *item; |
2875 | struct btrfs_disk_balance_args disk_bargs; | 2874 | struct btrfs_disk_balance_args disk_bargs; |
@@ -2882,29 +2881,30 @@ int btrfs_recover_balance(struct btrfs_root *tree_root) | |||
2882 | if (!path) | 2881 | if (!path) |
2883 | return -ENOMEM; | 2882 | return -ENOMEM; |
2884 | 2883 | ||
2885 | bctl = kzalloc(sizeof(*bctl), GFP_NOFS); | ||
2886 | if (!bctl) { | ||
2887 | ret = -ENOMEM; | ||
2888 | goto out; | ||
2889 | } | ||
2890 | |||
2891 | key.objectid = BTRFS_BALANCE_OBJECTID; | 2884 | key.objectid = BTRFS_BALANCE_OBJECTID; |
2892 | key.type = BTRFS_BALANCE_ITEM_KEY; | 2885 | key.type = BTRFS_BALANCE_ITEM_KEY; |
2893 | key.offset = 0; | 2886 | key.offset = 0; |
2894 | 2887 | ||
2895 | ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0); | 2888 | ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, path, 0, 0); |
2896 | if (ret < 0) | 2889 | if (ret < 0) |
2897 | goto out_bctl; | 2890 | goto out; |
2898 | if (ret > 0) { /* ret = -ENOENT; */ | 2891 | if (ret > 0) { /* ret = -ENOENT; */ |
2899 | ret = 0; | 2892 | ret = 0; |
2900 | goto out_bctl; | 2893 | goto out; |
2894 | } | ||
2895 | |||
2896 | bctl = kzalloc(sizeof(*bctl), GFP_NOFS); | ||
2897 | if (!bctl) { | ||
2898 | ret = -ENOMEM; | ||
2899 | goto out; | ||
2901 | } | 2900 | } |
2902 | 2901 | ||
2903 | leaf = path->nodes[0]; | 2902 | leaf = path->nodes[0]; |
2904 | item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_balance_item); | 2903 | item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_balance_item); |
2905 | 2904 | ||
2906 | bctl->fs_info = tree_root->fs_info; | 2905 | bctl->fs_info = fs_info; |
2907 | bctl->flags = btrfs_balance_flags(leaf, item) | BTRFS_BALANCE_RESUME; | 2906 | bctl->flags = btrfs_balance_flags(leaf, item); |
2907 | bctl->flags |= BTRFS_BALANCE_RESUME; | ||
2908 | 2908 | ||
2909 | btrfs_balance_data(leaf, item, &disk_bargs); | 2909 | btrfs_balance_data(leaf, item, &disk_bargs); |
2910 | btrfs_disk_balance_args_to_cpu(&bctl->data, &disk_bargs); | 2910 | btrfs_disk_balance_args_to_cpu(&bctl->data, &disk_bargs); |
@@ -2913,14 +2913,13 @@ int btrfs_recover_balance(struct btrfs_root *tree_root) | |||
2913 | btrfs_balance_sys(leaf, item, &disk_bargs); | 2913 | btrfs_balance_sys(leaf, item, &disk_bargs); |
2914 | btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs); | 2914 | btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs); |
2915 | 2915 | ||
2916 | tsk = kthread_run(balance_kthread, bctl, "btrfs-balance"); | 2916 | mutex_lock(&fs_info->volume_mutex); |
2917 | if (IS_ERR(tsk)) | 2917 | mutex_lock(&fs_info->balance_mutex); |
2918 | ret = PTR_ERR(tsk); | ||
2919 | else | ||
2920 | goto out; | ||
2921 | 2918 | ||
2922 | out_bctl: | 2919 | set_balance_control(bctl); |
2923 | kfree(bctl); | 2920 | |
2921 | mutex_unlock(&fs_info->balance_mutex); | ||
2922 | mutex_unlock(&fs_info->volume_mutex); | ||
2924 | out: | 2923 | out: |
2925 | btrfs_free_path(path); | 2924 | btrfs_free_path(path); |
2926 | return ret; | 2925 | return ret; |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 74366f27a76b..e1b1a649fc5a 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -281,7 +281,7 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size); | |||
281 | int btrfs_init_new_device(struct btrfs_root *root, char *path); | 281 | int btrfs_init_new_device(struct btrfs_root *root, char *path); |
282 | int btrfs_balance(struct btrfs_balance_control *bctl, | 282 | int btrfs_balance(struct btrfs_balance_control *bctl, |
283 | struct btrfs_ioctl_balance_args *bargs); | 283 | struct btrfs_ioctl_balance_args *bargs); |
284 | int btrfs_recover_balance(struct btrfs_root *tree_root); | 284 | int btrfs_recover_balance(struct btrfs_fs_info *fs_info); |
285 | int btrfs_pause_balance(struct btrfs_fs_info *fs_info); | 285 | int btrfs_pause_balance(struct btrfs_fs_info *fs_info); |
286 | int btrfs_cancel_balance(struct btrfs_fs_info *fs_info); | 286 | int btrfs_cancel_balance(struct btrfs_fs_info *fs_info); |
287 | int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset); | 287 | int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset); |