aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJan Schmidt <list.btrfs@jan-o-sch.net>2012-06-14 10:37:44 -0400
committerJan Schmidt <list.btrfs@jan-o-sch.net>2012-07-12 04:54:38 -0400
commit546adb0d817c34dc2be3a7cb5bba8771f837a562 (patch)
treee287f5cb18b6c97d6acdbc09dbb045dca95e7daa /fs/btrfs
parentbcef60f249034f69e89e544461cbfecb68975595 (diff)
Btrfs: hooks for qgroup to record delayed refs
Hooks into qgroup code to record refs and into transaction commit. This is the main entry point for qgroup. Basically every change in extent backrefs got accounted to the appropriate qgroups. Signed-off-by: Arne Jansen <sensille@gmx.net> Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Diffstat (limited to 'fs/btrfs')
-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 21a757717637..da7419ed01bb 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 2b5cb27f9861..0d7c90c366b6 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 d20d2e24f8d2..21c768cb443f 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);