aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2012-06-22 14:24:12 -0400
committerChris Mason <chris.mason@fusionio.com>2012-07-02 15:39:16 -0400
commit68310a5e42f93c2242ec1836c3b18d531e0065e2 (patch)
treecf457369274a1633ba02170fcb6aab0114906f0a /fs/btrfs
parentc3473e830074ef04f974f2829690942dd8580619 (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.c10
-rw-r--r--fs/btrfs/volumes.c39
-rw-r--r--fs/btrfs/volumes.h2
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
2870int btrfs_recover_balance(struct btrfs_root *tree_root) 2870int 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
2922out_bctl: 2919 set_balance_control(bctl);
2923 kfree(bctl); 2920
2921 mutex_unlock(&fs_info->balance_mutex);
2922 mutex_unlock(&fs_info->volume_mutex);
2924out: 2923out:
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);
281int btrfs_init_new_device(struct btrfs_root *root, char *path); 281int btrfs_init_new_device(struct btrfs_root *root, char *path);
282int btrfs_balance(struct btrfs_balance_control *bctl, 282int btrfs_balance(struct btrfs_balance_control *bctl,
283 struct btrfs_ioctl_balance_args *bargs); 283 struct btrfs_ioctl_balance_args *bargs);
284int btrfs_recover_balance(struct btrfs_root *tree_root); 284int btrfs_recover_balance(struct btrfs_fs_info *fs_info);
285int btrfs_pause_balance(struct btrfs_fs_info *fs_info); 285int btrfs_pause_balance(struct btrfs_fs_info *fs_info);
286int btrfs_cancel_balance(struct btrfs_fs_info *fs_info); 286int btrfs_cancel_balance(struct btrfs_fs_info *fs_info);
287int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset); 287int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset);