diff options
-rw-r--r-- | fs/btrfs/transaction.c | 31 |
1 files changed, 18 insertions, 13 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 07b985f2a814..2fe3ef5e9de3 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -1023,7 +1023,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
1023 | u64 old_root_bytenr; | 1023 | u64 old_root_bytenr; |
1024 | u64 old_root_used; | 1024 | u64 old_root_used; |
1025 | struct btrfs_root *tree_root = root->fs_info->tree_root; | 1025 | struct btrfs_root *tree_root = root->fs_info->tree_root; |
1026 | bool extent_root = (root->objectid == BTRFS_EXTENT_TREE_OBJECTID); | ||
1027 | 1026 | ||
1028 | old_root_used = btrfs_root_used(&root->root_item); | 1027 | old_root_used = btrfs_root_used(&root->root_item); |
1029 | btrfs_write_dirty_block_groups(trans, root); | 1028 | btrfs_write_dirty_block_groups(trans, root); |
@@ -1031,9 +1030,7 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
1031 | while (1) { | 1030 | while (1) { |
1032 | old_root_bytenr = btrfs_root_bytenr(&root->root_item); | 1031 | old_root_bytenr = btrfs_root_bytenr(&root->root_item); |
1033 | if (old_root_bytenr == root->node->start && | 1032 | if (old_root_bytenr == root->node->start && |
1034 | old_root_used == btrfs_root_used(&root->root_item) && | 1033 | old_root_used == btrfs_root_used(&root->root_item)) |
1035 | (!extent_root || | ||
1036 | list_empty(&trans->transaction->dirty_bgs))) | ||
1037 | break; | 1034 | break; |
1038 | 1035 | ||
1039 | btrfs_set_root_node(&root->root_item, root->node); | 1036 | btrfs_set_root_node(&root->root_item, root->node); |
@@ -1044,14 +1041,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
1044 | return ret; | 1041 | return ret; |
1045 | 1042 | ||
1046 | old_root_used = btrfs_root_used(&root->root_item); | 1043 | old_root_used = btrfs_root_used(&root->root_item); |
1047 | if (extent_root) { | ||
1048 | ret = btrfs_write_dirty_block_groups(trans, root); | ||
1049 | if (ret) | ||
1050 | return ret; | ||
1051 | } | ||
1052 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | ||
1053 | if (ret) | ||
1054 | return ret; | ||
1055 | } | 1044 | } |
1056 | 1045 | ||
1057 | return 0; | 1046 | return 0; |
@@ -1068,6 +1057,7 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
1068 | struct btrfs_root *root) | 1057 | struct btrfs_root *root) |
1069 | { | 1058 | { |
1070 | struct btrfs_fs_info *fs_info = root->fs_info; | 1059 | struct btrfs_fs_info *fs_info = root->fs_info; |
1060 | struct list_head *dirty_bgs = &trans->transaction->dirty_bgs; | ||
1071 | struct list_head *next; | 1061 | struct list_head *next; |
1072 | struct extent_buffer *eb; | 1062 | struct extent_buffer *eb; |
1073 | int ret; | 1063 | int ret; |
@@ -1099,7 +1089,7 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
1099 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | 1089 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); |
1100 | if (ret) | 1090 | if (ret) |
1101 | return ret; | 1091 | return ret; |
1102 | 1092 | again: | |
1103 | while (!list_empty(&fs_info->dirty_cowonly_roots)) { | 1093 | while (!list_empty(&fs_info->dirty_cowonly_roots)) { |
1104 | next = fs_info->dirty_cowonly_roots.next; | 1094 | next = fs_info->dirty_cowonly_roots.next; |
1105 | list_del_init(next); | 1095 | list_del_init(next); |
@@ -1112,8 +1102,23 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
1112 | ret = update_cowonly_root(trans, root); | 1102 | ret = update_cowonly_root(trans, root); |
1113 | if (ret) | 1103 | if (ret) |
1114 | return ret; | 1104 | return ret; |
1105 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | ||
1106 | if (ret) | ||
1107 | return ret; | ||
1115 | } | 1108 | } |
1116 | 1109 | ||
1110 | while (!list_empty(dirty_bgs)) { | ||
1111 | ret = btrfs_write_dirty_block_groups(trans, root); | ||
1112 | if (ret) | ||
1113 | return ret; | ||
1114 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | ||
1115 | if (ret) | ||
1116 | return ret; | ||
1117 | } | ||
1118 | |||
1119 | if (!list_empty(&fs_info->dirty_cowonly_roots)) | ||
1120 | goto again; | ||
1121 | |||
1117 | list_add_tail(&fs_info->extent_root->dirty_list, | 1122 | list_add_tail(&fs_info->extent_root->dirty_list, |
1118 | &trans->transaction->switch_commits); | 1123 | &trans->transaction->switch_commits); |
1119 | btrfs_after_dev_replace_commit(fs_info); | 1124 | btrfs_after_dev_replace_commit(fs_info); |