From 20705a84306611f17eb322ea2d4436dc288ee548 Mon Sep 17 00:00:00 2001 From: Ameer Hamza Date: Mon, 10 Mar 2025 00:07:31 +0500 Subject: [PATCH] Enforce default quotas when no per-ID quota is set Update zfs_id_overobjquota() and zfs_id_overblockquota() to enforce default user/group/project quotas (block and object-based) when no per-user, per-group, or per-project quota exists. If a specific quota is not configured for an ID, the default quota value is applied. Signed-off-by: Ameer Hamza Reviewed-by: Alexander Motin Reviewed-by: Tony Hutter --- module/zfs/zfs_quota.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/module/zfs/zfs_quota.c b/module/zfs/zfs_quota.c index 3f028a900..f534dec58 100644 --- a/module/zfs/zfs_quota.c +++ b/module/zfs/zfs_quota.c @@ -373,7 +373,7 @@ boolean_t zfs_id_overobjquota(zfsvfs_t *zfsvfs, uint64_t usedobj, uint64_t id) { char buf[20 + DMU_OBJACCT_PREFIX_LEN]; - uint64_t used, quota, quotaobj; + uint64_t used, quota, quotaobj, default_quota = 0; int err; if (!dmu_objset_userobjspace_present(zfsvfs->z_os)) { @@ -399,20 +399,29 @@ zfs_id_overobjquota(zfsvfs_t *zfsvfs, uint64_t usedobj, uint64_t id) return (B_FALSE); } quotaobj = zfsvfs->z_projectobjquota_obj; + default_quota = zfsvfs->z_defaultprojectobjquota; } else if (usedobj == DMU_USERUSED_OBJECT) { quotaobj = zfsvfs->z_userobjquota_obj; + default_quota = zfsvfs->z_defaultuserobjquota; } else if (usedobj == DMU_GROUPUSED_OBJECT) { quotaobj = zfsvfs->z_groupobjquota_obj; + default_quota = zfsvfs->z_defaultgroupobjquota; } else { return (B_FALSE); } - if (quotaobj == 0 || zfsvfs->z_replay) + if (zfsvfs->z_replay) return (B_FALSE); (void) snprintf(buf, sizeof (buf), "%llx", (longlong_t)id); - err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, "a); - if (err != 0) - return (B_FALSE); + if (quotaobj == 0) { + if (default_quota == 0) + return (B_FALSE); + quota = default_quota; + } else { + err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, "a); + if (err != 0 && ((quota = default_quota) == 0)) + return (B_FALSE); + } (void) snprintf(buf, sizeof (buf), DMU_OBJACCT_PREFIX "%llx", (longlong_t)id); @@ -426,7 +435,7 @@ boolean_t zfs_id_overblockquota(zfsvfs_t *zfsvfs, uint64_t usedobj, uint64_t id) { char buf[20]; - uint64_t used, quota, quotaobj; + uint64_t used, quota, quotaobj, default_quota = 0; int err; if (usedobj == DMU_PROJECTUSED_OBJECT) { @@ -441,20 +450,29 @@ zfs_id_overblockquota(zfsvfs_t *zfsvfs, uint64_t usedobj, uint64_t id) return (B_FALSE); } quotaobj = zfsvfs->z_projectquota_obj; + default_quota = zfsvfs->z_defaultprojectquota; } else if (usedobj == DMU_USERUSED_OBJECT) { quotaobj = zfsvfs->z_userquota_obj; + default_quota = zfsvfs->z_defaultuserquota; } else if (usedobj == DMU_GROUPUSED_OBJECT) { quotaobj = zfsvfs->z_groupquota_obj; + default_quota = zfsvfs->z_defaultgroupquota; } else { return (B_FALSE); } - if (quotaobj == 0 || zfsvfs->z_replay) + if (zfsvfs->z_replay) return (B_FALSE); (void) snprintf(buf, sizeof (buf), "%llx", (longlong_t)id); - err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, "a); - if (err != 0) - return (B_FALSE); + if (quotaobj == 0) { + if (default_quota == 0) + return (B_FALSE); + quota = default_quota; + } else { + err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, "a); + if (err != 0 && ((quota = default_quota) == 0)) + return (B_FALSE); + } err = zap_lookup(zfsvfs->z_os, usedobj, buf, 8, 1, &used); if (err != 0)