On Mon, Apr 25, 2022 at 09:33:00AM -0700, Darrick J. Wong wrote: > On Wed, Apr 20, 2022 at 04:45:07PM +0200, Andrey Albershteyn wrote: > > The implementation based on XFS_GETQUOTA call for each ID in range, > > specified with -L/-U, is quite slow for wider ranges. > > > > If kernel supports XFS_GETNEXTQUOTA, report_*_mount/dump_any_file > > will use that to obtain quota list for the mount. XFS_GETNEXTQUOTA > > returns quota of the requested ID and next ID with non-empty quota. > > > > Otherwise, XFS_GETQUOTA will be used for each user/group/project ID > > known from password/group/project database. > > > > Signed-off-by: Andrey Albershteyn <aalbersh@xxxxxxxxxx> > > Reviewed-by: Christoph Hellwig <hch@xxxxxx> > > --- > > quota/report.c | 116 +++++++++++++++---------------------------------- > > 1 file changed, 35 insertions(+), 81 deletions(-) > > > > diff --git a/quota/report.c b/quota/report.c > > index 8ca154f0..65d931f3 100644 > > --- a/quota/report.c > > +++ b/quota/report.c > > @@ -135,7 +135,7 @@ dump_limits_any_type( > > { > > fs_path_t *mount; > > struct fs_disk_quota d; > > - uint id = 0, oid; > > + uint id = lower, oid, flags = 0; > > > > if ((mount = fs_table_lookup(dir, FS_MOUNT_POINT)) == NULL) { > > exitcode = 1; > > @@ -144,27 +144,17 @@ dump_limits_any_type( > > return; > > } > > > > - /* Range was specified; query everything in it */ > > - if (upper) { > > - for (id = lower; id <= upper; id++) { > > - get_dquot(&d, id, &oid, type, mount->fs_name, 0); > > - dump_file(fp, &d, mount->fs_name); > > - } > > - return; > > - } > > - > > - /* Use GETNEXTQUOTA if it's available */ > > - if (get_dquot(&d, id, &oid, type, mount->fs_name, GETNEXTQUOTA_FLAG)) { > > + while (get_dquot(&d, id, &oid, type, > > + mount->fs_name, flags | GETNEXTQUOTA_FLAG) && > > + !(upper && (d.d_id > upper))) { > > dump_file(fp, &d, mount->fs_name); > > id = oid + 1; > > Just out of curiosity, could this be "id = d.d_id + 1", and then you > don't have to pass around &oid at all? yeah I think it can be removed (haven't noticed that it's not needed anymore), I will resend it together with fix to another your comment > > --D > > > - while (get_dquot(&d, id, &oid, type, mount->fs_name, > > - GETNEXTQUOTA_FLAG)) { > > - dump_file(fp, &d, mount->fs_name); > > - id = oid + 1; > > - } > > - return; > > + flags |= GETNEXTQUOTA_FLAG; > > } > > > > + if (flags & GETNEXTQUOTA_FLAG) > > + return; > > + > > /* Otherwise fall back to iterating over each uid/gid/prjid */ > > switch (type) { > > case XFS_GROUP_QUOTA: { > > @@ -472,31 +462,19 @@ report_user_mount( > > { > > struct passwd *u; > > struct fs_disk_quota d; > > - uint id = 0, oid; > > + uint id = lower, oid; > > > > - if (upper) { /* identifier range specified */ > > - for (id = lower; id <= upper; id++) { > > - if (get_dquot(&d, id, NULL, XFS_USER_QUOTA, > > - mount->fs_name, flags)) { > > - report_mount(fp, &d, NULL, form, XFS_USER_QUOTA, > > - mount, flags); > > - flags |= NO_HEADER_FLAG; > > - } > > - } > > - } else if (get_dquot(&d, id, &oid, XFS_USER_QUOTA, mount->fs_name, > > - flags|GETNEXTQUOTA_FLAG)) { > > - report_mount(fp, &d, NULL, form, XFS_USER_QUOTA, mount, > > - flags|GETNEXTQUOTA_FLAG); > > + while (get_dquot(&d, id, &oid, XFS_USER_QUOTA, > > + mount->fs_name, flags | GETNEXTQUOTA_FLAG) && > > + !(upper && (d.d_id > upper))) { > > + report_mount(fp, &d, NULL, form, XFS_USER_QUOTA, mount, flags); > > id = oid + 1; > > flags |= GETNEXTQUOTA_FLAG; > > flags |= NO_HEADER_FLAG; > > - while (get_dquot(&d, id, &oid, XFS_USER_QUOTA, mount->fs_name, > > - flags)) { > > - report_mount(fp, &d, NULL, form, XFS_USER_QUOTA, > > - mount, flags); > > - id = oid + 1; > > - } > > - } else { > > + } > > + > > + /* No GETNEXTQUOTA support, iterate over all from password file */ > > + if (!(flags & GETNEXTQUOTA_FLAG)) { > > setpwent(); > > while ((u = getpwent()) != NULL) { > > if (get_dquot(&d, u->pw_uid, NULL, XFS_USER_QUOTA, > > @@ -524,31 +502,19 @@ report_group_mount( > > { > > struct group *g; > > struct fs_disk_quota d; > > - uint id = 0, oid; > > + uint id = lower, oid; > > > > - if (upper) { /* identifier range specified */ > > - for (id = lower; id <= upper; id++) { > > - if (get_dquot(&d, id, NULL, XFS_GROUP_QUOTA, > > - mount->fs_name, flags)) { > > - report_mount(fp, &d, NULL, form, > > - XFS_GROUP_QUOTA, mount, flags); > > - flags |= NO_HEADER_FLAG; > > - } > > - } > > - } else if (get_dquot(&d, id, &oid, XFS_GROUP_QUOTA, > > - mount->fs_name, flags|GETNEXTQUOTA_FLAG)) { > > - report_mount(fp, &d, NULL, form, XFS_GROUP_QUOTA, mount, > > - flags|GETNEXTQUOTA_FLAG); > > + while (get_dquot(&d, id, &oid, XFS_GROUP_QUOTA, > > + mount->fs_name, flags | GETNEXTQUOTA_FLAG) && > > + !(upper && (oid > upper))) { > > + report_mount(fp, &d, NULL, form, XFS_GROUP_QUOTA, mount, flags); > > id = oid + 1; > > flags |= GETNEXTQUOTA_FLAG; > > flags |= NO_HEADER_FLAG; > > - while (get_dquot(&d, id, &oid, XFS_GROUP_QUOTA, > > - mount->fs_name, flags)) { > > - report_mount(fp, &d, NULL, form, XFS_GROUP_QUOTA, mount, > > - flags); > > - id = oid + 1; > > - } > > - } else { > > + } > > + > > + /* No GETNEXTQUOTA support, iterate over all from password file */ > > + if (!(flags & GETNEXTQUOTA_FLAG)) { > > setgrent(); > > while ((g = getgrent()) != NULL) { > > if (get_dquot(&d, g->gr_gid, NULL, XFS_GROUP_QUOTA, > > @@ -575,31 +541,19 @@ report_project_mount( > > { > > fs_project_t *p; > > struct fs_disk_quota d; > > - uint id = 0, oid; > > + uint id = lower, oid; > > > > - if (upper) { /* identifier range specified */ > > - for (id = lower; id <= upper; id++) { > > - if (get_dquot(&d, id, NULL, XFS_PROJ_QUOTA, > > - mount->fs_name, flags)) { > > - report_mount(fp, &d, NULL, form, XFS_PROJ_QUOTA, > > - mount, flags); > > - flags |= NO_HEADER_FLAG; > > - } > > - } > > - } else if (get_dquot(&d, id, &oid, XFS_PROJ_QUOTA, > > - mount->fs_name, flags|GETNEXTQUOTA_FLAG)) { > > - report_mount(fp, &d, NULL, form, XFS_PROJ_QUOTA, mount, > > - flags|GETNEXTQUOTA_FLAG); > > + while (get_dquot(&d, id, &oid, XFS_PROJ_QUOTA, > > + mount->fs_name, flags | GETNEXTQUOTA_FLAG) && > > + !(upper && (d.d_id > upper))) { > > + report_mount(fp, &d, NULL, form, XFS_PROJ_QUOTA, mount, flags); > > id = oid + 1; > > flags |= GETNEXTQUOTA_FLAG; > > flags |= NO_HEADER_FLAG; > > - while (get_dquot(&d, id, &oid, XFS_PROJ_QUOTA, > > - mount->fs_name, flags)) { > > - report_mount(fp, &d, NULL, form, XFS_PROJ_QUOTA, mount, > > - flags); > > - id = oid + 1; > > - } > > - } else { > > + } > > + > > + /* No GETNEXTQUOTA support, iterate over all */ > > + if (!(flags & GETNEXTQUOTA_FLAG)) { > > if (!getprprid(0)) { > > /* > > * Print default project quota, even if projid 0 > > -- > > 2.27.0 > > > -- - Andrey