aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.c16
-rw-r--r--fs/btrfs/ctree.h1
-rw-r--r--fs/btrfs/transaction.c9
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 */
214static void add_root_to_dirty_list(struct btrfs_root *root) 214static 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,