Message ID | 20220420144507.269754-5-aalbersh@redhat.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | xfsprogs: optimize -L/-U range calls for xfs_quota's dump/report | expand |
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@redhat.com> > Reviewed-by: Christoph Hellwig <hch@lst.de> > --- > 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? --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 >
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@redhat.com> > > Reviewed-by: Christoph Hellwig <hch@lst.de> > > --- > > 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 > > >
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