From 9cb9a59e1c5653c9335808996e88b1bbbe6f3b7a Mon Sep 17 00:00:00 2001 From: Ameer Hamza Date: Thu, 6 Mar 2025 03:10:24 +0500 Subject: [PATCH] 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 Reviewed-by: Alexander Motin Reviewed-by: Tony Hutter --- module/os/freebsd/zfs/zfs_vfsops.c | 36 +++++++++++++----------- module/os/linux/zfs/zfs_vfsops.c | 44 ++++++++++++++++++------------ 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/module/os/freebsd/zfs/zfs_vfsops.c b/module/os/freebsd/zfs/zfs_vfsops.c index c192f6834..493ac9f69 100644 --- a/module/os/freebsd/zfs/zfs_vfsops.c +++ b/module/os/freebsd/zfs/zfs_vfsops.c @@ -241,35 +241,40 @@ zfs_getquota(zfsvfs_t *zfsvfs, uid_t id, int isgroup, struct dqblk64 *dqp) { int error = 0; char buf[32]; - uint64_t usedobj, quotaobj; + uint64_t usedobj, quotaobj, defaultquota; uint64_t quota, used = 0; timespec_t now; usedobj = isgroup ? DMU_GROUPUSED_OBJECT : DMU_USERUSED_OBJECT; 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); - if ((error = zap_lookup(zfsvfs->z_os, quotaobj, - buf, sizeof (quota), 1, "a)) != 0) { - dprintf("%s(%d): quotaobj lookup failed\n", - __FUNCTION__, __LINE__); - goto done; + if (quotaobj == 0) { + if (defaultquota == 0) + return (ENOENT); + quota = defaultquota; + } else { + error = zap_lookup(zfsvfs->z_os, quotaobj, buf, sizeof (quota), + 1, "a); + if (error && (quota = defaultquota) == 0) + return (error); } + /* * quota(8) uses bsoftlimit as "quoota", and hardlimit as "limit". * So we set them to be the same. */ dqp->dqb_bsoftlimit = dqp->dqb_bhardlimit = btodb(quota); error = zap_lookup(zfsvfs->z_os, usedobj, buf, sizeof (used), 1, &used); - if (error && error != ENOENT) { - dprintf("%s(%d): usedobj failed; %d\n", - __FUNCTION__, __LINE__, error); - goto done; - } + if (error == ENOENT) + error = 0; + if (error) + return (error); dqp->dqb_curblocks = btodb(used); dqp->dqb_ihardlimit = dqp->dqb_isoftlimit = 0; vfs_timestamp(&now); @@ -279,7 +284,6 @@ zfs_getquota(zfsvfs_t *zfsvfs, uid_t id, int isgroup, struct dqblk64 *dqp) * particularly useful. */ dqp->dqb_btime = dqp->dqb_itime = now.tv_sec; -done: return (error); } diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c index ba38d6673..3682c7500 100644 --- a/module/os/linux/zfs/zfs_vfsops.c +++ b/module/os/linux/zfs/zfs_vfsops.c @@ -1068,15 +1068,19 @@ zfs_statfs_project(zfsvfs_t *zfsvfs, znode_t *zp, struct kstatfs *statp, if (err) return (err); - if (zfsvfs->z_projectquota_obj == 0) - goto objs; - - err = zap_lookup(zfsvfs->z_os, zfsvfs->z_projectquota_obj, - buf + offset, 8, 1, "a); - if (err == ENOENT) - goto objs; - else if (err) - return (err); + if (zfsvfs->z_projectquota_obj == 0) { + if (zfsvfs->z_defaultprojectquota == 0) + goto objs; + quota = zfsvfs->z_defaultprojectquota; + } else { + err = zap_lookup(zfsvfs->z_os, zfsvfs->z_projectquota_obj, + buf + offset, 8, 1, "a); + if (err && (quota = zfsvfs->z_defaultprojectquota) == 0) { + if (err == ENOENT) + goto objs; + return (err); + } + } err = zap_lookup(zfsvfs->z_os, DMU_PROJECTUSED_OBJECT, 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; objs: - if (zfsvfs->z_projectobjquota_obj == 0) - return (0); - err = zap_lookup(zfsvfs->z_os, zfsvfs->z_projectobjquota_obj, - buf + offset, 8, 1, "a); - if (err == ENOENT) - return (0); - else if (err) - return (err); + if (zfsvfs->z_projectobjquota_obj == 0) { + if (zfsvfs->z_defaultprojectobjquota == 0) + return (0); + quota = zfsvfs->z_defaultprojectobjquota; + } else { + err = zap_lookup(zfsvfs->z_os, zfsvfs->z_projectobjquota_obj, + buf + offset, 8, 1, "a); + if (err && (quota = zfsvfs->z_defaultprojectobjquota) == 0) { + if (err == ENOENT) + return (0); + return (err); + } + } + err = zap_lookup(zfsvfs->z_os, DMU_PROJECTUSED_OBJECT, buf, 8, 1, &used);