Hello Jan, > The function is separated into a preparation part and the three accounting > steps mentioned in the qgroups documentation. The goal is to make steps two > and three usable by the rescan functionality. A side effect is that the > function is restructured into readable subunits.
How about renaming the three functions like: 1> qgroup_walk_old_roots() 2> qgroup_walk_new_root() 3> qgroup_rewalk_old_root() I'd like this function to be meaningful, but not just step1,2,3. Maybe you can think out better function name. Thanks, Wang > > Signed-off-by: Jan Schmidt <list.bt...@jan-o-sch.net> > --- > fs/btrfs/qgroup.c | 212 > ++++++++++++++++++++++++++++++----------------------- > 1 files changed, 121 insertions(+), 91 deletions(-) > > diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c > index b44124d..c38a0c5 100644 > --- a/fs/btrfs/qgroup.c > +++ b/fs/btrfs/qgroup.c > @@ -1075,6 +1075,122 @@ int btrfs_qgroup_record_ref(struct btrfs_trans_handle > *trans, > return 0; > } > > +static void qgroup_account_ref_step1(struct btrfs_fs_info *fs_info, > + struct ulist *roots, struct ulist *tmp, > + u64 seq) > +{ > + struct ulist_node *unode; > + struct ulist_iterator uiter; > + struct ulist_node *tmp_unode; > + struct ulist_iterator tmp_uiter; > + struct btrfs_qgroup *qg; > + > + ULIST_ITER_INIT(&uiter); > + while ((unode = ulist_next(roots, &uiter))) { > + qg = find_qgroup_rb(fs_info, unode->val); > + if (!qg) > + continue; > + > + ulist_reinit(tmp); > + /* XXX id not needed */ > + ulist_add(tmp, qg->qgroupid, (u64)(uintptr_t)qg, GFP_ATOMIC); > + ULIST_ITER_INIT(&tmp_uiter); > + while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) { > + struct btrfs_qgroup_list *glist; > + > + qg = (struct btrfs_qgroup *)(uintptr_t)tmp_unode->aux; > + if (qg->refcnt < seq) > + qg->refcnt = seq + 1; > + else > + ++qg->refcnt; > + > + list_for_each_entry(glist, &qg->groups, next_group) { > + ulist_add(tmp, glist->group->qgroupid, > + (u64)(uintptr_t)glist->group, > + GFP_ATOMIC); > + } > + } > + } > +} > + > +static void qgroup_account_ref_step2(struct btrfs_fs_info *fs_info, > + struct ulist *roots, struct ulist *tmp, > + u64 seq, int sgn, u64 num_bytes, > + struct btrfs_qgroup *qgroup) > +{ > + struct ulist_node *unode; > + struct ulist_iterator uiter; > + struct btrfs_qgroup *qg; > + struct btrfs_qgroup_list *glist; > + > + ulist_reinit(tmp); > + ulist_add(tmp, qgroup->qgroupid, (uintptr_t)qgroup, GFP_ATOMIC); > + > + ULIST_ITER_INIT(&uiter); > + while ((unode = ulist_next(tmp, &uiter))) { > + > + qg = (struct btrfs_qgroup *)(uintptr_t)unode->aux; > + if (qg->refcnt < seq) { > + /* not visited by step 1 */ > + qg->rfer += sgn * num_bytes; > + qg->rfer_cmpr += sgn * num_bytes; > + if (roots->nnodes == 0) { > + qg->excl += sgn * num_bytes; > + qg->excl_cmpr += sgn * num_bytes; > + } > + qgroup_dirty(fs_info, qg); > + } > + WARN_ON(qg->tag >= seq); > + qg->tag = seq; > + > + list_for_each_entry(glist, &qg->groups, next_group) { > + ulist_add(tmp, glist->group->qgroupid, > + (uintptr_t)glist->group, GFP_ATOMIC); > + } > + } > +} > + > +static void qgroup_account_ref_step3(struct btrfs_fs_info *fs_info, > + struct ulist *roots, struct ulist *tmp, > + u64 seq, int sgn, u64 num_bytes) > +{ > + struct ulist_node *unode; > + struct ulist_iterator uiter; > + struct btrfs_qgroup *qg; > + struct ulist_node *tmp_unode; > + struct ulist_iterator tmp_uiter; > + > + ULIST_ITER_INIT(&uiter); > + while ((unode = ulist_next(roots, &uiter))) { > + qg = find_qgroup_rb(fs_info, unode->val); > + if (!qg) > + continue; > + > + ulist_reinit(tmp); > + ulist_add(tmp, qg->qgroupid, (uintptr_t)qg, GFP_ATOMIC); > + ULIST_ITER_INIT(&tmp_uiter); > + while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) { > + struct btrfs_qgroup_list *glist; > + > + qg = (struct btrfs_qgroup *)(uintptr_t)tmp_unode->aux; > + if (qg->tag == seq) > + continue; > + > + if (qg->refcnt - seq == roots->nnodes) { > + qg->excl -= sgn * num_bytes; > + qg->excl_cmpr -= sgn * num_bytes; > + qgroup_dirty(fs_info, qg); > + } > + > + list_for_each_entry(glist, &qg->groups, next_group) { > + ulist_add(tmp, glist->group->qgroupid, > + (uintptr_t)glist->group, > + GFP_ATOMIC); > + } > + } > + } > +} > + > /* > * btrfs_qgroup_account_ref is called for every ref that is added to or > deleted > * from the fs. First, all roots referencing the extent are searched, and > @@ -1090,10 +1206,8 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle > *trans, > struct btrfs_root *quota_root; > u64 ref_root; > struct btrfs_qgroup *qgroup; > - struct ulist_node *unode; > struct ulist *roots = NULL; > struct ulist *tmp = NULL; > - struct ulist_iterator uiter; > u64 seq; > int ret = 0; > int sgn; > @@ -1175,103 +1289,19 @@ int btrfs_qgroup_account_ref(struct > btrfs_trans_handle *trans, > seq = fs_info->qgroup_seq; > fs_info->qgroup_seq += roots->nnodes + 1; /* max refcnt */ > > - ULIST_ITER_INIT(&uiter); > - while ((unode = ulist_next(roots, &uiter))) { > - struct ulist_node *tmp_unode; > - struct ulist_iterator tmp_uiter; > - struct btrfs_qgroup *qg; > - > - qg = find_qgroup_rb(fs_info, unode->val); > - if (!qg) > - continue; > - > - ulist_reinit(tmp); > - /* XXX id not needed */ > - ulist_add(tmp, qg->qgroupid, (u64)(uintptr_t)qg, GFP_ATOMIC); > - ULIST_ITER_INIT(&tmp_uiter); > - while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) { > - struct btrfs_qgroup_list *glist; > - > - qg = (struct btrfs_qgroup *)(uintptr_t)tmp_unode->aux; > - if (qg->refcnt < seq) > - qg->refcnt = seq + 1; > - else > - ++qg->refcnt; > - > - list_for_each_entry(glist, &qg->groups, next_group) { > - ulist_add(tmp, glist->group->qgroupid, > - (u64)(uintptr_t)glist->group, > - GFP_ATOMIC); > - } > - } > - } > + qgroup_account_ref_step1(fs_info, roots, tmp, seq); > > /* > * step 2: walk from the new root > */ > - ulist_reinit(tmp); > - ulist_add(tmp, qgroup->qgroupid, (uintptr_t)qgroup, GFP_ATOMIC); > - ULIST_ITER_INIT(&uiter); > - while ((unode = ulist_next(tmp, &uiter))) { > - struct btrfs_qgroup *qg; > - struct btrfs_qgroup_list *glist; > - > - qg = (struct btrfs_qgroup *)(uintptr_t)unode->aux; > - if (qg->refcnt < seq) { > - /* not visited by step 1 */ > - qg->rfer += sgn * node->num_bytes; > - qg->rfer_cmpr += sgn * node->num_bytes; > - if (roots->nnodes == 0) { > - qg->excl += sgn * node->num_bytes; > - qg->excl_cmpr += sgn * node->num_bytes; > - } > - qgroup_dirty(fs_info, qg); > - } > - WARN_ON(qg->tag >= seq); > - qg->tag = seq; > - > - list_for_each_entry(glist, &qg->groups, next_group) { > - ulist_add(tmp, glist->group->qgroupid, > - (uintptr_t)glist->group, GFP_ATOMIC); > - } > - } > + qgroup_account_ref_step2(fs_info, roots, tmp, seq, sgn, > + node->num_bytes, qgroup); > > /* > * step 3: walk again from old refs > */ > - ULIST_ITER_INIT(&uiter); > - while ((unode = ulist_next(roots, &uiter))) { > - struct btrfs_qgroup *qg; > - struct ulist_node *tmp_unode; > - struct ulist_iterator tmp_uiter; > - > - qg = find_qgroup_rb(fs_info, unode->val); > - if (!qg) > - continue; > - > - ulist_reinit(tmp); > - ulist_add(tmp, qg->qgroupid, (uintptr_t)qg, GFP_ATOMIC); > - ULIST_ITER_INIT(&tmp_uiter); > - while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) { > - struct btrfs_qgroup_list *glist; > - > - qg = (struct btrfs_qgroup *)(uintptr_t)tmp_unode->aux; > - if (qg->tag == seq) > - continue; > - > - if (qg->refcnt - seq == roots->nnodes) { > - qg->excl -= sgn * node->num_bytes; > - qg->excl_cmpr -= sgn * node->num_bytes; > - qgroup_dirty(fs_info, qg); > - } > - > - list_for_each_entry(glist, &qg->groups, next_group) { > - ulist_add(tmp, glist->group->qgroupid, > - (uintptr_t)glist->group, > - GFP_ATOMIC); > - } > - } > - } > + qgroup_account_ref_step3(fs_info, roots, tmp, seq, sgn, > + node->num_bytes); > ret = 0; > unlock: > spin_unlock(&fs_info->qgroup_lock); -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html