On Fri 22-01-16 12:25:32, Eric Sandeen wrote: > Q_GETNEXTQUOTA is exactly like Q_GETQUOTA, 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. > > This does require a new data structure for userspace, as the > current structure does not include an ID for the returned quota > information. > > Today, Ext4 with a hidden quota inode requires 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> The patch seems to be missing addition of Q_GETNEXTQUOTA into quotactl_cmd_write(). Otherwise it looks good to me. Honza > --- > fs/quota/quota.c | 30 ++++++++++++++++++++++++++++++ > include/uapi/linux/quota.h | 14 ++++++++++++++ > 2 files changed, 44 insertions(+), 0 deletions(-) > > diff --git a/fs/quota/quota.c b/fs/quota/quota.c > index 0a6dd71..ffa4e0b 100644 > --- a/fs/quota/quota.c > +++ b/fs/quota/quota.c > @@ -222,6 +222,34 @@ static int quota_getquota(struct super_block *sb, int type, qid_t id, > return 0; > } > > +/* > + * Return quota for next active quota >= this id, if any exists, > + * otherwise return -ESRCH via ->get_nextdqblk > + */ > +static int quota_getnextquota(struct super_block *sb, int type, qid_t id, > + void __user *addr) > +{ > + struct kqid qid; > + struct qc_dqblk fdq; > + struct if_nextdqblk idq; > + 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, &fdq); > + if (ret) > + return ret; > + /* struct if_nextdqblk is a superset of struct if_dqblk */ > + copy_to_if_dqblk((struct if_dqblk *)&idq, &fdq); > + idq.dqb_id = from_kqid(current_user_ns(), qid); > + if (copy_to_user(addr, &idq, sizeof(idq))) > + return -EFAULT; > + return 0; > +} > + > static void copy_from_if_dqblk(struct qc_dqblk *dst, struct if_dqblk *src) > { > dst->d_spc_hardlimit = qbtos(src->dqb_bhardlimit); > @@ -698,6 +726,8 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, > return quota_setinfo(sb, type, addr); > case Q_GETQUOTA: > return quota_getquota(sb, type, id, addr); > + case Q_GETNEXTQUOTA: > + return quota_getnextquota(sb, type, id, addr); > case Q_SETQUOTA: > return quota_setquota(sb, type, id, addr); > case Q_SYNC: > diff --git a/include/uapi/linux/quota.h b/include/uapi/linux/quota.h > index 9c95b2c..38baddb 100644 > --- a/include/uapi/linux/quota.h > +++ b/include/uapi/linux/quota.h > @@ -71,6 +71,7 @@ > #define Q_SETINFO 0x800006 /* set information about quota files */ > #define Q_GETQUOTA 0x800007 /* get user quota structure */ > #define Q_SETQUOTA 0x800008 /* set user quota structure */ > +#define Q_GETNEXTQUOTA 0x800009 /* get disk limits and usage >= ID */ > > /* Quota format type IDs */ > #define QFMT_VFS_OLD 1 > @@ -119,6 +120,19 @@ struct if_dqblk { > __u32 dqb_valid; > }; > > +struct if_nextdqblk { > + __u64 dqb_bhardlimit; > + __u64 dqb_bsoftlimit; > + __u64 dqb_curspace; > + __u64 dqb_ihardlimit; > + __u64 dqb_isoftlimit; > + __u64 dqb_curinodes; > + __u64 dqb_btime; > + __u64 dqb_itime; > + __u32 dqb_valid; > + __u32 dqb_id; > +}; > + > /* > * Structure used for setting quota information about file via quotactl > * Following flags are used to specify which fields are valid > -- > 1.7.1 > -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs