aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/delayed-ref.c16
-rw-r--r--fs/btrfs/delayed-ref.h19
-rw-r--r--fs/btrfs/transaction.c7
3 files changed, 36 insertions, 6 deletions
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
index 21a75771763..da7419ed01b 100644
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -529,8 +529,8 @@ static noinline void add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
529 ref->is_head = 0; 529 ref->is_head = 0;
530 ref->in_tree = 1; 530 ref->in_tree = 1;
531 531
532 if (is_fstree(ref_root)) 532 if (need_ref_seq(for_cow, ref_root))
533 seq = btrfs_inc_tree_mod_seq(fs_info); 533 seq = btrfs_get_tree_mod_seq(fs_info, &trans->delayed_ref_elem);
534 ref->seq = seq; 534 ref->seq = seq;
535 535
536 full_ref = btrfs_delayed_node_to_tree_ref(ref); 536 full_ref = btrfs_delayed_node_to_tree_ref(ref);
@@ -588,8 +588,8 @@ static noinline void add_delayed_data_ref(struct btrfs_fs_info *fs_info,
588 ref->is_head = 0; 588 ref->is_head = 0;
589 ref->in_tree = 1; 589 ref->in_tree = 1;
590 590
591 if (is_fstree(ref_root)) 591 if (need_ref_seq(for_cow, ref_root))
592 seq = btrfs_inc_tree_mod_seq(fs_info); 592 seq = btrfs_get_tree_mod_seq(fs_info, &trans->delayed_ref_elem);
593 ref->seq = seq; 593 ref->seq = seq;
594 594
595 full_ref = btrfs_delayed_node_to_data_ref(ref); 595 full_ref = btrfs_delayed_node_to_data_ref(ref);
@@ -662,10 +662,12 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
662 add_delayed_tree_ref(fs_info, trans, &ref->node, bytenr, 662 add_delayed_tree_ref(fs_info, trans, &ref->node, bytenr,
663 num_bytes, parent, ref_root, level, action, 663 num_bytes, parent, ref_root, level, action,
664 for_cow); 664 for_cow);
665 if (!is_fstree(ref_root) && 665 if (!need_ref_seq(for_cow, ref_root) &&
666 waitqueue_active(&fs_info->tree_mod_seq_wait)) 666 waitqueue_active(&fs_info->tree_mod_seq_wait))
667 wake_up(&fs_info->tree_mod_seq_wait); 667 wake_up(&fs_info->tree_mod_seq_wait);
668 spin_unlock(&delayed_refs->lock); 668 spin_unlock(&delayed_refs->lock);
669 if (need_ref_seq(for_cow, ref_root))
670 btrfs_qgroup_record_ref(trans, &ref->node, extent_op);
669 671
670 return 0; 672 return 0;
671} 673}
@@ -711,10 +713,12 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
711 add_delayed_data_ref(fs_info, trans, &ref->node, bytenr, 713 add_delayed_data_ref(fs_info, trans, &ref->node, bytenr,
712 num_bytes, parent, ref_root, owner, offset, 714 num_bytes, parent, ref_root, owner, offset,
713 action, for_cow); 715 action, for_cow);
714 if (!is_fstree(ref_root) && 716 if (!need_ref_seq(for_cow, ref_root) &&
715 waitqueue_active(&fs_info->tree_mod_seq_wait)) 717 waitqueue_active(&fs_info->tree_mod_seq_wait))
716 wake_up(&fs_info->tree_mod_seq_wait); 718 wake_up(&fs_info->tree_mod_seq_wait);
717 spin_unlock(&delayed_refs->lock); 719 spin_unlock(&delayed_refs->lock);
720 if (need_ref_seq(for_cow, ref_root))
721 btrfs_qgroup_record_ref(trans, &ref->node, extent_op);
718 722
719 return 0; 723 return 0;
720} 724}
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h
index 2b5cb27f986..0d7c90c366b 100644
--- a/fs/btrfs/delayed-ref.h
+++ b/fs/btrfs/delayed-ref.h
@@ -180,6 +180,25 @@ int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info,
180 u64 seq); 180 u64 seq);
181 181
182/* 182/*
183 * delayed refs with a ref_seq > 0 must be held back during backref walking.
184 * this only applies to items in one of the fs-trees. for_cow items never need
185 * to be held back, so they won't get a ref_seq number.
186 */
187static inline int need_ref_seq(int for_cow, u64 rootid)
188{
189 if (for_cow)
190 return 0;
191
192 if (rootid == BTRFS_FS_TREE_OBJECTID)
193 return 1;
194
195 if ((s64)rootid >= (s64)BTRFS_FIRST_FREE_OBJECTID)
196 return 1;
197
198 return 0;
199}
200
201/*
183 * a node might live in a head or a regular ref, this lets you 202 * a node might live in a head or a regular ref, this lets you
184 * test for the proper type to use. 203 * test for the proper type to use.
185 */ 204 */
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index d20d2e24f8d..21c768cb443 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -795,6 +795,13 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
795 ret = btrfs_run_dev_stats(trans, root->fs_info); 795 ret = btrfs_run_dev_stats(trans, root->fs_info);
796 BUG_ON(ret); 796 BUG_ON(ret);
797 797
798 ret = btrfs_run_qgroups(trans, root->fs_info);
799 BUG_ON(ret);
800
801 /* run_qgroups might have added some more refs */
802 ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
803 BUG_ON(ret);
804
798 while (!list_empty(&fs_info->dirty_cowonly_roots)) { 805 while (!list_empty(&fs_info->dirty_cowonly_roots)) {
799 next = fs_info->dirty_cowonly_roots.next; 806 next = fs_info->dirty_cowonly_roots.next;
800 list_del_init(next); 807 list_del_init(next);