|
@@ -1023,7 +1023,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
|
|
|
u64 old_root_bytenr;
|
|
|
u64 old_root_used;
|
|
|
struct btrfs_root *tree_root = root->fs_info->tree_root;
|
|
|
- bool extent_root = (root->objectid == BTRFS_EXTENT_TREE_OBJECTID);
|
|
|
|
|
|
old_root_used = btrfs_root_used(&root->root_item);
|
|
|
btrfs_write_dirty_block_groups(trans, root);
|
|
@@ -1031,9 +1030,7 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
|
|
|
while (1) {
|
|
|
old_root_bytenr = btrfs_root_bytenr(&root->root_item);
|
|
|
if (old_root_bytenr == root->node->start &&
|
|
|
- old_root_used == btrfs_root_used(&root->root_item) &&
|
|
|
- (!extent_root ||
|
|
|
- list_empty(&trans->transaction->dirty_bgs)))
|
|
|
+ old_root_used == btrfs_root_used(&root->root_item))
|
|
|
break;
|
|
|
|
|
|
btrfs_set_root_node(&root->root_item, root->node);
|
|
@@ -1044,14 +1041,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
|
|
|
return ret;
|
|
|
|
|
|
old_root_used = btrfs_root_used(&root->root_item);
|
|
|
- if (extent_root) {
|
|
|
- ret = btrfs_write_dirty_block_groups(trans, root);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- }
|
|
|
- ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -1068,6 +1057,7 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
|
|
|
struct btrfs_root *root)
|
|
|
{
|
|
|
struct btrfs_fs_info *fs_info = root->fs_info;
|
|
|
+ struct list_head *dirty_bgs = &trans->transaction->dirty_bgs;
|
|
|
struct list_head *next;
|
|
|
struct extent_buffer *eb;
|
|
|
int ret;
|
|
@@ -1099,7 +1089,7 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
|
|
|
ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
-
|
|
|
+again:
|
|
|
while (!list_empty(&fs_info->dirty_cowonly_roots)) {
|
|
|
next = fs_info->dirty_cowonly_roots.next;
|
|
|
list_del_init(next);
|
|
@@ -1112,8 +1102,23 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
|
|
|
ret = update_cowonly_root(trans, root);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
+ ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
+ while (!list_empty(dirty_bgs)) {
|
|
|
+ ret = btrfs_write_dirty_block_groups(trans, root);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!list_empty(&fs_info->dirty_cowonly_roots))
|
|
|
+ goto again;
|
|
|
+
|
|
|
list_add_tail(&fs_info->extent_root->dirty_list,
|
|
|
&trans->transaction->switch_commits);
|
|
|
btrfs_after_dev_replace_commit(fs_info);
|