diff options
-rw-r--r-- | fs/btrfs/ctree.c | 16 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 9 |
3 files changed, 21 insertions, 5 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 14a72ed14ef7..97a98fc07cfc 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -213,11 +213,19 @@ static struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root) | |||
213 | */ | 213 | */ |
214 | static void add_root_to_dirty_list(struct btrfs_root *root) | 214 | static void add_root_to_dirty_list(struct btrfs_root *root) |
215 | { | 215 | { |
216 | if (test_bit(BTRFS_ROOT_DIRTY, &root->state) || | ||
217 | !test_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state)) | ||
218 | return; | ||
219 | |||
216 | spin_lock(&root->fs_info->trans_lock); | 220 | spin_lock(&root->fs_info->trans_lock); |
217 | if (test_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state) && | 221 | if (!test_and_set_bit(BTRFS_ROOT_DIRTY, &root->state)) { |
218 | list_empty(&root->dirty_list)) { | 222 | /* Want the extent tree to be the last on the list */ |
219 | list_add(&root->dirty_list, | 223 | if (root->objectid == BTRFS_EXTENT_TREE_OBJECTID) |
220 | &root->fs_info->dirty_cowonly_roots); | 224 | list_move_tail(&root->dirty_list, |
225 | &root->fs_info->dirty_cowonly_roots); | ||
226 | else | ||
227 | list_move(&root->dirty_list, | ||
228 | &root->fs_info->dirty_cowonly_roots); | ||
221 | } | 229 | } |
222 | spin_unlock(&root->fs_info->trans_lock); | 230 | spin_unlock(&root->fs_info->trans_lock); |
223 | } | 231 | } |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 7e607416755a..45ed4dc6a0ce 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1775,6 +1775,7 @@ struct btrfs_subvolume_writers { | |||
1775 | #define BTRFS_ROOT_DEFRAG_RUNNING 6 | 1775 | #define BTRFS_ROOT_DEFRAG_RUNNING 6 |
1776 | #define BTRFS_ROOT_FORCE_COW 7 | 1776 | #define BTRFS_ROOT_FORCE_COW 7 |
1777 | #define BTRFS_ROOT_MULTI_LOG_TASKS 8 | 1777 | #define BTRFS_ROOT_MULTI_LOG_TASKS 8 |
1778 | #define BTRFS_ROOT_DIRTY 9 | ||
1778 | 1779 | ||
1779 | /* | 1780 | /* |
1780 | * in ram representation of the tree. extent_root is used for all allocations | 1781 | * in ram representation of the tree. extent_root is used for all allocations |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index a605d4e2f2bc..aa2219ebecc9 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -1020,6 +1020,7 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
1020 | u64 old_root_bytenr; | 1020 | u64 old_root_bytenr; |
1021 | u64 old_root_used; | 1021 | u64 old_root_used; |
1022 | struct btrfs_root *tree_root = root->fs_info->tree_root; | 1022 | struct btrfs_root *tree_root = root->fs_info->tree_root; |
1023 | bool extent_root = (root->objectid == BTRFS_EXTENT_TREE_OBJECTID); | ||
1023 | 1024 | ||
1024 | old_root_used = btrfs_root_used(&root->root_item); | 1025 | old_root_used = btrfs_root_used(&root->root_item); |
1025 | btrfs_write_dirty_block_groups(trans, root); | 1026 | btrfs_write_dirty_block_groups(trans, root); |
@@ -1038,7 +1039,12 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
1038 | return ret; | 1039 | return ret; |
1039 | 1040 | ||
1040 | old_root_used = btrfs_root_used(&root->root_item); | 1041 | old_root_used = btrfs_root_used(&root->root_item); |
1041 | ret = btrfs_write_dirty_block_groups(trans, root); | 1042 | if (extent_root) { |
1043 | ret = btrfs_write_dirty_block_groups(trans, root); | ||
1044 | if (ret) | ||
1045 | return ret; | ||
1046 | } | ||
1047 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | ||
1042 | if (ret) | 1048 | if (ret) |
1043 | return ret; | 1049 | return ret; |
1044 | } | 1050 | } |
@@ -1097,6 +1103,7 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
1097 | next = fs_info->dirty_cowonly_roots.next; | 1103 | next = fs_info->dirty_cowonly_roots.next; |
1098 | list_del_init(next); | 1104 | list_del_init(next); |
1099 | root = list_entry(next, struct btrfs_root, dirty_list); | 1105 | root = list_entry(next, struct btrfs_root, dirty_list); |
1106 | clear_bit(BTRFS_ROOT_DIRTY, &root->state); | ||
1100 | 1107 | ||
1101 | if (root != fs_info->extent_root) | 1108 | if (root != fs_info->extent_root) |
1102 | list_add_tail(&root->dirty_list, | 1109 | list_add_tail(&root->dirty_list, |