diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/delayed-ref.c | 16 | ||||
-rw-r--r-- | fs/btrfs/delayed-ref.h | 19 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 7 |
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 | */ | ||
187 | static 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); |