]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tmpfiles: do not mandate `STATX_ATIME` and `STATX_MTIME` 41232/head
authorIvan Shapovalov <intelfx@intelfx.name>
Fri, 20 Mar 2026 15:45:07 +0000 (16:45 +0100)
committerIvan Shapovalov <intelfx@intelfx.name>
Mon, 6 Apr 2026 20:53:00 +0000 (22:53 +0200)
Timestamps are not guaranteed to be set by `statx()`, and their presence
should not be asserted as a proxy to judge the kernel version. In
particular, `STATX_ATIME` is omitted from the return when querying a
file on a `noatime` superblock, causing spurious errors from tmpfiles.

Correctness analysis
====================

The timestamps produced by the `statx()` call in `opendir_and_stat()`
are only ever used once, in `clean_item_instance()` (lines 3148-3149)
as inputs to `dir_cleanup()`. Convert absent timestamps into
`NSEC_INFINITY` as per the previous commit.

Fixes #41227.

src/tmpfiles/tmpfiles.c

index 2b1c612f5ceff1e330b7c97214c0c6ae25b20cb4..baef92f7af5d374b0502d7294357710b80f04791 100644 (file)
@@ -591,8 +591,8 @@ static int opendir_and_stat(
                         /* path= */ NULL,
                         AT_EMPTY_PATH,
                         /* xstatx_flags= */ 0,
-                        STATX_MODE|STATX_INO|STATX_ATIME|STATX_MTIME,
-                        /* optional_mask= */ 0,
+                        STATX_MODE|STATX_INO,
+                        STATX_ATIME|STATX_MTIME,
                         STATX_ATTR_MOUNT_ROOT,
                         &sx);
         if (r < 0)
@@ -3124,6 +3124,7 @@ static int clean_item_instance(
                 return 0;
 
         usec_t cutoff = n - i->age;
+        nsec_t atime_nsec, mtime_nsec;
 
         _cleanup_closedir_ DIR *d = NULL;
         struct statx sx;
@@ -3134,6 +3135,9 @@ static int clean_item_instance(
         if (r <= 0)
                 return r;
 
+        atime_nsec = FLAGS_SET(sx.stx_mask, STATX_ATIME) ? statx_timestamp_load_nsec(&sx.stx_atime) : NSEC_INFINITY;
+        mtime_nsec = FLAGS_SET(sx.stx_mask, STATX_MTIME) ? statx_timestamp_load_nsec(&sx.stx_mtime) : NSEC_INFINITY;
+
         if (DEBUG_LOGGING) {
                 _cleanup_free_ char *ab_f = NULL, *ab_d = NULL;
 
@@ -3153,8 +3157,8 @@ static int clean_item_instance(
         }
 
         return dir_cleanup(c, i, instance, d,
-                           statx_timestamp_load_nsec(&sx.stx_atime),
-                           statx_timestamp_load_nsec(&sx.stx_mtime),
+                           atime_nsec,
+                           mtime_nsec,
                            cutoff * NSEC_PER_USEC,
                            sx.stx_dev_major, sx.stx_dev_minor,
                            mountpoint,