tmpfiles: do not require STATX_ATIME (#41232)
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: ```console # SYSTEMD_LOG_LEVEL=debug systemd-tmpfiles --clean <...> Running clean action for entry X /var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-*/tmp statx() does not support 'STATX_ATIME' mask (running on an old kernel?) statx(/var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-prometheus-smartctl-exporter.service-GKguQK/tmp) failed: Protocol driver not attached statx() does not support 'STATX_ATIME' mask (running on an old kernel?) statx(/var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-systemd-logind.service-k8j52T/tmp) failed: Protocol driver not attached statx() does not support 'STATX_ATIME' mask (running on an old kernel?) statx(/var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-irqbalance.service-7RJkev/tmp) failed: Protocol driver not attached statx() does not support 'STATX_ATIME' mask (running on an old kernel?) statx(/var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-chronyd.service-8hkO5G/tmp) failed: Protocol driver not attached statx() does not support 'STATX_ATIME' mask (running on an old kernel?) statx(/var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-dbus-broker.service-6P6LVl/tmp) failed: Protocol driver not attached statx() does not support 'STATX_ATIME' mask (running on an old kernel?) statx(/var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-nginx.service-B5HX8B/tmp) failed: Protocol driver not attached Running clean action for entry x /var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-* Running clean action for entry q /var/tmp statx() does not support 'STATX_ATIME' mask (running on an old kernel?) statx(/var/tmp) failed: Protocol driver not attached <...> ``` Additionally, refactor `dir_cleanup()` slightly for self-consistency to make it evident that the `NSEC_INFINITY` transformation is correct. Fixes #41227.
This commit is contained in:
@@ -114,6 +114,7 @@ struct timespec* timespec_store(struct timespec *ts, usec_t u);
|
||||
struct timespec* timespec_store_nsec(struct timespec *ts, nsec_t n);
|
||||
|
||||
#define TIMESPEC_STORE(u) timespec_store(&(struct timespec) {}, (u))
|
||||
#define TIMESPEC_STORE_NSEC(n) timespec_store_nsec(&(struct timespec) {}, (n))
|
||||
|
||||
usec_t timeval_load(const struct timeval *tv) _pure_;
|
||||
struct timeval* timeval_store(struct timeval *tv, usec_t u);
|
||||
|
||||
+24
-12
@@ -592,8 +592,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)
|
||||
@@ -711,10 +711,10 @@ static int dir_cleanup(
|
||||
continue;
|
||||
}
|
||||
|
||||
atime_nsec = FLAGS_SET(sx.stx_mask, STATX_ATIME) ? statx_timestamp_load_nsec(&sx.stx_atime) : 0;
|
||||
mtime_nsec = FLAGS_SET(sx.stx_mask, STATX_MTIME) ? statx_timestamp_load_nsec(&sx.stx_mtime) : 0;
|
||||
ctime_nsec = FLAGS_SET(sx.stx_mask, STATX_CTIME) ? statx_timestamp_load_nsec(&sx.stx_ctime) : 0;
|
||||
btime_nsec = FLAGS_SET(sx.stx_mask, STATX_BTIME) ? statx_timestamp_load_nsec(&sx.stx_btime) : 0;
|
||||
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;
|
||||
ctime_nsec = FLAGS_SET(sx.stx_mask, STATX_CTIME) ? statx_timestamp_load_nsec(&sx.stx_ctime) : NSEC_INFINITY;
|
||||
btime_nsec = FLAGS_SET(sx.stx_mask, STATX_BTIME) ? statx_timestamp_load_nsec(&sx.stx_btime) : NSEC_INFINITY;
|
||||
|
||||
sub_path = path_join(p, de->d_name);
|
||||
if (!sub_path) {
|
||||
@@ -868,11 +868,19 @@ finish:
|
||||
log_action("Would restore", "Restoring",
|
||||
"%s access and modification time on \"%s\": %s, %s",
|
||||
p,
|
||||
FORMAT_TIMESTAMP_STYLE(self_atime_nsec / NSEC_PER_USEC, TIMESTAMP_US),
|
||||
FORMAT_TIMESTAMP_STYLE(self_mtime_nsec / NSEC_PER_USEC, TIMESTAMP_US));
|
||||
self_atime_nsec != NSEC_INFINITY
|
||||
? FORMAT_TIMESTAMP_STYLE(self_atime_nsec / NSEC_PER_USEC, TIMESTAMP_US)
|
||||
: "(omitted)",
|
||||
self_mtime_nsec != NSEC_INFINITY
|
||||
? FORMAT_TIMESTAMP_STYLE(self_mtime_nsec / NSEC_PER_USEC, TIMESTAMP_US)
|
||||
: "(omitted)");
|
||||
|
||||
timespec_store_nsec(ts + 0, self_atime_nsec);
|
||||
timespec_store_nsec(ts + 1, self_mtime_nsec);
|
||||
ts[0] = self_atime_nsec != NSEC_INFINITY
|
||||
? *TIMESPEC_STORE_NSEC(self_atime_nsec)
|
||||
: TIMESPEC_OMIT;
|
||||
ts[1] = self_mtime_nsec != NSEC_INFINITY
|
||||
? *TIMESPEC_STORE_NSEC(self_mtime_nsec)
|
||||
: TIMESPEC_OMIT;
|
||||
|
||||
/* Restore original directory timestamps */
|
||||
if (!arg_dry_run &&
|
||||
@@ -3117,6 +3125,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;
|
||||
@@ -3127,6 +3136,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;
|
||||
|
||||
@@ -3146,8 +3158,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,
|
||||
|
||||
Reference in New Issue
Block a user