xfs
[Top] [All Lists]

Re: [PATCH 2/7] quota: add new quotactl Q_XGETNEXTQUOTA

To: Eric Sandeen <sandeen@xxxxxxxxxx>
Subject: Re: [PATCH 2/7] quota: add new quotactl Q_XGETNEXTQUOTA
From: Jan Kara <jack@xxxxxxx>
Date: Mon, 25 Jan 2016 15:51:40 +0100
Cc: linux-fsdevel@xxxxxxxxxxxxxxx, xfs@xxxxxxxxxxx, jack@xxxxxxx
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1453487136-12681-3-git-send-email-sandeen@xxxxxxxxxx>
References: <1453487136-12681-1-git-send-email-sandeen@xxxxxxxxxx> <1453487136-12681-3-git-send-email-sandeen@xxxxxxxxxx>
User-agent: Mutt/1.5.24 (2015-08-30)
On Fri 22-01-16 12:25:31, Eric Sandeen wrote:
> Q_XGETNEXTQUOTA is exactly like Q_XGETQUOTA, except that it
> will return quota information for the id equal to or greater
> than the id requested.  In other words, if the requested id has
> no quota, the command will return quota information for the
> next higher id which does have a quota set.  If no higher id
> has an active quota, -ESRCH is returned.
> 
> This allows filesystems to do efficient iteration in kernelspace,
> much like extN filesystems do in userspace when asked to report
> all active quotas.
> 
> The patch adds a d_id field to struct qc_dqblk so that we can
> pass back the id of the quota which was found, and return it
> to userspace.

This paragraph is no longer true. Otherwise the patch looks good to me.

                                                                Honza

> 
> Today, filesystems such as XFS require getpwent-style iterations,
> and for systems which have i.e. LDAP backends, this can be very
> slow, or even impossible if iteration is not allowed in the
> configuration.
> 
> Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx>
> ---
>  fs/quota/quota.c               |   31 +++++++++++++++++++++++++++++++
>  include/linux/quota.h          |    2 ++
>  include/uapi/linux/dqblk_xfs.h |    1 +
>  3 files changed, 34 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/quota/quota.c b/fs/quota/quota.c
> index ea66670..0a6dd71 100644
> --- a/fs/quota/quota.c
> +++ b/fs/quota/quota.c
> @@ -625,6 +625,34 @@ static int quota_getxquota(struct super_block *sb, int 
> type, qid_t id,
>       return ret;
>  }
>  
> +/*
> + * Return quota for next active quota >= this id, if any exists,
> + * otherwise return -ESRCH via ->get_nextdqblk.
> + */
> +static int quota_getnextxquota(struct super_block *sb, int type, qid_t id,
> +                         void __user *addr)
> +{
> +     struct fs_disk_quota fdq;
> +     struct qc_dqblk qdq;
> +     struct kqid qid;
> +     qid_t id_out;
> +     int ret;
> +
> +     if (!sb->s_qcop->get_nextdqblk)
> +             return -ENOSYS;
> +     qid = make_kqid(current_user_ns(), type, id);
> +     if (!qid_valid(qid))
> +             return -EINVAL;
> +     ret = sb->s_qcop->get_nextdqblk(sb, &qid, &qdq);
> +     if (ret)
> +             return ret;
> +     id_out = from_kqid(current_user_ns(), qid);
> +     copy_to_xfs_dqblk(&fdq, &qdq, type, id_out);
> +     if (copy_to_user(addr, &fdq, sizeof(fdq)))
> +             return -EFAULT;
> +     return ret;
> +}
> +
>  static int quota_rmxquota(struct super_block *sb, void __user *addr)
>  {
>       __u32 flags;
> @@ -690,6 +718,8 @@ static int do_quotactl(struct super_block *sb, int type, 
> int cmd, qid_t id,
>               return quota_setxquota(sb, type, id, addr);
>       case Q_XGETQUOTA:
>               return quota_getxquota(sb, type, id, addr);
> +     case Q_XGETNEXTQUOTA:
> +             return quota_getnextxquota(sb, type, id, addr);
>       case Q_XQUOTASYNC:
>               if (sb->s_flags & MS_RDONLY)
>                       return -EROFS;
> @@ -712,6 +742,7 @@ static int quotactl_cmd_write(int cmd)
>       case Q_XGETQSTAT:
>       case Q_XGETQSTATV:
>       case Q_XGETQUOTA:
> +     case Q_XGETNEXTQUOTA:
>       case Q_XQUOTASYNC:
>               return 0;
>       }
> diff --git a/include/linux/quota.h b/include/linux/quota.h
> index b2505ac..fba92f5 100644
> --- a/include/linux/quota.h
> +++ b/include/linux/quota.h
> @@ -425,6 +425,8 @@ struct quotactl_ops {
>       int (*quota_sync)(struct super_block *, int);
>       int (*set_info)(struct super_block *, int, struct qc_info *);
>       int (*get_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
> +     int (*get_nextdqblk)(struct super_block *, struct kqid *,
> +                          struct qc_dqblk *);
>       int (*set_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
>       int (*get_state)(struct super_block *, struct qc_state *);
>       int (*rm_xquota)(struct super_block *, unsigned int);
> diff --git a/include/uapi/linux/dqblk_xfs.h b/include/uapi/linux/dqblk_xfs.h
> index dcd75cc..11b3b31 100644
> --- a/include/uapi/linux/dqblk_xfs.h
> +++ b/include/uapi/linux/dqblk_xfs.h
> @@ -39,6 +39,7 @@
>  #define Q_XQUOTARM   XQM_CMD(6)      /* free disk space used by dquots */
>  #define Q_XQUOTASYNC XQM_CMD(7)      /* delalloc flush, updates dquots */
>  #define Q_XGETQSTATV XQM_CMD(8)      /* newer version of get quota */
> +#define Q_XGETNEXTQUOTA      XQM_CMD(9)      /* get disk limits and usage >= 
> ID */
>  
>  /*
>   * fs_disk_quota structure:
> -- 
> 1.7.1
> 
-- 
Jan Kara <jack@xxxxxxxx>
SUSE Labs, CR

<Prev in Thread] Current Thread [Next in Thread>