]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fstab-generator: fix spurious quota warning for xfs
authorVincent Mihalkovic <vmihalko@redhat.com>
Mon, 11 May 2026 11:52:49 +0000 (13:52 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 19 May 2026 12:12:43 +0000 (13:12 +0100)
Filesystems like xfs, btrfs, gfs2 and ocfs2 handle quotas internally
and do not need external quotacheck/quotaon services. When usrquota or
grpquota mount options are used in fstab for these filesystems,
generator_hook_up_quotacheck() falls through to the !fstype_needs_quota()
branch and emits a misleading warning that quotas are "not supported"
when they actually work fine — the kernel handles them internally.

Add fstype_has_internal_quota() to return early with a debug message,
and adopt a tri-state return convention so the caller skips quotaon
when quotacheck was not needed.

The buggy code path was introduced in #24824 and #24880.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
src/basic/mountpoint-util.c
src/basic/mountpoint-util.h
src/fstab-generator/fstab-generator.c
src/shared/generator.c

index 958e34bc5326f112178d467830aa22a4a4605275..7c043bb54a4b9b4b0a2866e4f6e4565f6e0ea649 100644 (file)
@@ -385,6 +385,17 @@ bool fstype_needs_quota(const char *fstype) {
                           "f2fs");
 }
 
+bool fstype_has_internal_quota(const char *fstype) {
+        /* These filesystems have built-in quota support and do not need
+         * external quotacheck/quotaon services - see the "nothing needed"
+         * entries in fstype_needs_quota() above. */
+        return STR_IN_SET(fstype,
+                          "xfs",
+                          "gfs2",
+                          "ocfs2",
+                          "btrfs");
+}
+
 bool fstype_is_api_vfs(const char *fstype) {
         assert(fstype);
 
index 1381f3d8aba0ec32579fec35b4aa48bbcab52059..8cc966751c9c63a70600bf7270ea95644bcce0d8 100644 (file)
@@ -61,6 +61,7 @@ static inline int path_is_mount_point(const char *path) {
 
 bool fstype_is_network(const char *fstype);
 bool fstype_needs_quota(const char *fstype);
+bool fstype_has_internal_quota(const char *fstype);
 bool fstype_is_api_vfs(const char *fstype);
 bool fstype_is_blockdev_backed(const char *fstype);
 bool fstype_is_ro(const char *fsype);
index 572f30a1cf7f42851c732e67802dffc18813cbf3..2c23d285010276e82313493d8e028cd117eb87d9 100644 (file)
@@ -704,7 +704,7 @@ static int add_mount(
                 if (r < 0) {
                         if (r != -EOPNOTSUPP)
                                 return r;
-                } else {
+                } else if (r > 0) {
                         r = generator_hook_up_quotaon(dest, where, target_unit);
                         if (r < 0)
                                 return r;
index fd527b3e6d65a2aa1380b47b319189c302592870..5e2f8f6e0e64f2fb03275e8c9529b708e489b84c 100644 (file)
@@ -817,12 +817,18 @@ int generator_hook_up_quotacheck(
 
         if (isempty(fstype) || streq(fstype, "auto"))
                 return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Couldn't determine filesystem type for %s, quota cannot be activated", what);
+        if (fstype_has_internal_quota(fstype)) {
+                log_debug("%s handles quotas internally, skipping quotacheck/quotaon setup for %s", fstype, what);
+                return 0;
+        }
         if (!fstype_needs_quota(fstype))
                 return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Quota was requested for %s, but not supported, ignoring: %s", what, fstype);
 
         /* quotacheck unit for system root */
-        if (path_equal(where, "/"))
-                return generator_add_symlink(dir, SPECIAL_LOCAL_FS_TARGET, "wants", SYSTEM_DATA_UNIT_DIR "/" SPECIAL_QUOTACHECK_ROOT_SERVICE);
+        if (path_equal(where, "/")) {
+                r = generator_add_symlink(dir, SPECIAL_LOCAL_FS_TARGET, "wants", SYSTEM_DATA_UNIT_DIR "/" SPECIAL_QUOTACHECK_ROOT_SERVICE);
+                return r < 0 ? r : 1;
+        }
 
         r = unit_name_path_escape(where, &instance);
         if (r < 0)
@@ -838,7 +844,8 @@ int generator_hook_up_quotacheck(
         if (r < 0)
                 return log_error_errno(r, "Failed to make unit name from path '%s': %m", where);
 
-        return generator_add_symlink_full(dir, where_unit, "wants", SYSTEM_DATA_UNIT_DIR "/" SPECIAL_QUOTACHECK_SERVICE, instance);
+        r = generator_add_symlink_full(dir, where_unit, "wants", SYSTEM_DATA_UNIT_DIR "/" SPECIAL_QUOTACHECK_SERVICE, instance);
+        return r < 0 ? r : 1;
 }
 
 int generator_hook_up_quotaon(