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

Reply via email to