Report default quotas via kernel interfaces

Ensure default user/group/project quotas are visible through quota
tools and filesystem stats when no per-ID quota is configured. This
maintains consistency between quota visibility and configured defaults.

Signed-off-by: Ameer Hamza <ahamza@ixsystems.com>

Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
This commit is contained in:
Ameer Hamza 2025-03-06 03:10:24 +05:00 committed by Tony Hutter
parent 20705a8430
commit 9cb9a59e1c
2 changed files with 47 additions and 33 deletions

View File

@ -241,35 +241,40 @@ zfs_getquota(zfsvfs_t *zfsvfs, uid_t id, int isgroup, struct dqblk64 *dqp)
{ {
int error = 0; int error = 0;
char buf[32]; char buf[32];
uint64_t usedobj, quotaobj; uint64_t usedobj, quotaobj, defaultquota;
uint64_t quota, used = 0; uint64_t quota, used = 0;
timespec_t now; timespec_t now;
usedobj = isgroup ? DMU_GROUPUSED_OBJECT : DMU_USERUSED_OBJECT; usedobj = isgroup ? DMU_GROUPUSED_OBJECT : DMU_USERUSED_OBJECT;
quotaobj = isgroup ? zfsvfs->z_groupquota_obj : zfsvfs->z_userquota_obj; quotaobj = isgroup ? zfsvfs->z_groupquota_obj : zfsvfs->z_userquota_obj;
defaultquota = isgroup ? zfsvfs->z_defaultgroupquota :
zfsvfs->z_defaultuserquota;
if (zfsvfs->z_replay)
return (ENOENT);
if (quotaobj == 0 || zfsvfs->z_replay) {
error = ENOENT;
goto done;
}
(void) sprintf(buf, "%llx", (longlong_t)id); (void) sprintf(buf, "%llx", (longlong_t)id);
if ((error = zap_lookup(zfsvfs->z_os, quotaobj, if (quotaobj == 0) {
buf, sizeof (quota), 1, &quota)) != 0) { if (defaultquota == 0)
dprintf("%s(%d): quotaobj lookup failed\n", return (ENOENT);
__FUNCTION__, __LINE__); quota = defaultquota;
goto done; } else {
error = zap_lookup(zfsvfs->z_os, quotaobj, buf, sizeof (quota),
1, &quota);
if (error && (quota = defaultquota) == 0)
return (error);
} }
/* /*
* quota(8) uses bsoftlimit as "quoota", and hardlimit as "limit". * quota(8) uses bsoftlimit as "quoota", and hardlimit as "limit".
* So we set them to be the same. * So we set them to be the same.
*/ */
dqp->dqb_bsoftlimit = dqp->dqb_bhardlimit = btodb(quota); dqp->dqb_bsoftlimit = dqp->dqb_bhardlimit = btodb(quota);
error = zap_lookup(zfsvfs->z_os, usedobj, buf, sizeof (used), 1, &used); error = zap_lookup(zfsvfs->z_os, usedobj, buf, sizeof (used), 1, &used);
if (error && error != ENOENT) { if (error == ENOENT)
dprintf("%s(%d): usedobj failed; %d\n", error = 0;
__FUNCTION__, __LINE__, error); if (error)
goto done; return (error);
}
dqp->dqb_curblocks = btodb(used); dqp->dqb_curblocks = btodb(used);
dqp->dqb_ihardlimit = dqp->dqb_isoftlimit = 0; dqp->dqb_ihardlimit = dqp->dqb_isoftlimit = 0;
vfs_timestamp(&now); vfs_timestamp(&now);
@ -279,7 +284,6 @@ zfs_getquota(zfsvfs_t *zfsvfs, uid_t id, int isgroup, struct dqblk64 *dqp)
* particularly useful. * particularly useful.
*/ */
dqp->dqb_btime = dqp->dqb_itime = now.tv_sec; dqp->dqb_btime = dqp->dqb_itime = now.tv_sec;
done:
return (error); return (error);
} }

View File

@ -1068,15 +1068,19 @@ zfs_statfs_project(zfsvfs_t *zfsvfs, znode_t *zp, struct kstatfs *statp,
if (err) if (err)
return (err); return (err);
if (zfsvfs->z_projectquota_obj == 0) if (zfsvfs->z_projectquota_obj == 0) {
goto objs; if (zfsvfs->z_defaultprojectquota == 0)
goto objs;
err = zap_lookup(zfsvfs->z_os, zfsvfs->z_projectquota_obj, quota = zfsvfs->z_defaultprojectquota;
buf + offset, 8, 1, &quota); } else {
if (err == ENOENT) err = zap_lookup(zfsvfs->z_os, zfsvfs->z_projectquota_obj,
goto objs; buf + offset, 8, 1, &quota);
else if (err) if (err && (quota = zfsvfs->z_defaultprojectquota) == 0) {
return (err); if (err == ENOENT)
goto objs;
return (err);
}
}
err = zap_lookup(zfsvfs->z_os, DMU_PROJECTUSED_OBJECT, err = zap_lookup(zfsvfs->z_os, DMU_PROJECTUSED_OBJECT,
buf + offset, 8, 1, &used); buf + offset, 8, 1, &used);
@ -1102,15 +1106,21 @@ zfs_statfs_project(zfsvfs_t *zfsvfs, znode_t *zp, struct kstatfs *statp,
statp->f_bavail = statp->f_bfree; statp->f_bavail = statp->f_bfree;
objs: objs:
if (zfsvfs->z_projectobjquota_obj == 0)
return (0);
err = zap_lookup(zfsvfs->z_os, zfsvfs->z_projectobjquota_obj, if (zfsvfs->z_projectobjquota_obj == 0) {
buf + offset, 8, 1, &quota); if (zfsvfs->z_defaultprojectobjquota == 0)
if (err == ENOENT) return (0);
return (0); quota = zfsvfs->z_defaultprojectobjquota;
else if (err) } else {
return (err); err = zap_lookup(zfsvfs->z_os, zfsvfs->z_projectobjquota_obj,
buf + offset, 8, 1, &quota);
if (err && (quota = zfsvfs->z_defaultprojectobjquota) == 0) {
if (err == ENOENT)
return (0);
return (err);
}
}
err = zap_lookup(zfsvfs->z_os, DMU_PROJECTUSED_OBJECT, err = zap_lookup(zfsvfs->z_os, DMU_PROJECTUSED_OBJECT,
buf, 8, 1, &used); buf, 8, 1, &used);