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; - 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