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); |
