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. Actually, is -ESRCH the right return value? It seems XFS traditionally returns -ENOENT when id doesn't exist. So that would look more logical to me. Honza > 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. > > 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 _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs