]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
stat-util: drop statx_fallback()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 28 Feb 2025 10:19:23 +0000 (19:19 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 28 Feb 2025 15:33:32 +0000 (00:33 +0900)
Now both our required baseline of glibc and kernel support statx.

src/basic/dirent-util.c
src/basic/fd-util.c
src/basic/recurse-dir.c
src/basic/stat-util.c
src/basic/stat-util.h
src/shared/find-esp.c
src/tmpfiles/tmpfiles.c

index 51db9820f9cc95e68164a5126a1594fd347022a3..e25097d8aee568291a3e03a82a53984f112f7b1f 100644 (file)
@@ -10,7 +10,6 @@
 
 int dirent_ensure_type(int dir_fd, struct dirent *de) {
         struct statx sx;
-        int r;
 
         assert(dir_fd >= 0);
         assert(de);
@@ -24,9 +23,8 @@ int dirent_ensure_type(int dir_fd, struct dirent *de) {
         }
 
         /* Let's ask only for the type, nothing else. */
-        r = statx_fallback(dir_fd, de->d_name, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT, STATX_TYPE, &sx);
-        if (r < 0)
-                return r;
+        if (statx(dir_fd, de->d_name, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT, STATX_TYPE, &sx) < 0)
+                return -errno;
 
         assert(FLAGS_SET(sx.stx_mask, STATX_TYPE));
         de->d_type = IFTODT(sx.stx_mode);
index 2691210d9182de7c4fd62f29264d68a5b7880102..8329c44a56b744a5460ff421912ec346ef00e86e 100644 (file)
@@ -1093,13 +1093,11 @@ int fds_are_same_mount(int fd1, int fd2) {
         assert(fd1 >= 0);
         assert(fd2 >= 0);
 
-        r = statx_fallback(fd1, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx1);
-        if (r < 0)
-                return r;
+        if (statx(fd1, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx1) < 0)
+                return -errno;
 
-        r = statx_fallback(fd2, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx2);
-        if (r < 0)
-                return r;
+        if (statx(fd2, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx2) < 0)
+                return -errno;
 
         /* First, compare inode. If these are different, the fd does not point to the root directory "/". */
         if (!statx_inode_same(&sx1, &sx2))
index 18e06551681e4adf6c2541460717c7e7eaffb06c..9612b7c6a50b3c07f83095758fb19cfdd8d4eca9 100644 (file)
@@ -167,9 +167,8 @@ int recurse_dir(
 
         if (FLAGS_SET(flags, RECURSE_DIR_TOPLEVEL)) {
                 if (statx_mask != 0) {
-                        r = statx_fallback(dir_fd, "", AT_EMPTY_PATH, statx_mask, &root_sx);
-                        if (r < 0)
-                                return r;
+                        if (statx(dir_fd, "", AT_EMPTY_PATH, statx_mask, &root_sx) < 0)
+                                return -errno;
                 }
 
                 r = func(RECURSE_DIR_ENTER,
@@ -247,9 +246,8 @@ int recurse_dir(
                                 de->entries[i]->d_type = DT_DIR;
 
                                 if (statx_mask != 0 || (flags & RECURSE_DIR_SAME_MOUNT)) {
-                                        r = statx_fallback(subdir_fd, "", AT_EMPTY_PATH, statx_mask, &sx);
-                                        if (r < 0)
-                                                return r;
+                                        if (statx(subdir_fd, "", AT_EMPTY_PATH, statx_mask, &sx) < 0)
+                                                return -errno;
 
                                         sx_valid = true;
                                 }
@@ -289,9 +287,8 @@ int recurse_dir(
                                  * assume. Let's guarantee that we never pass statx data of a directory where
                                  * caller expects a non-directory */
 
-                                r = statx_fallback(inode_fd, "", AT_EMPTY_PATH, statx_mask | STATX_TYPE, &sx);
-                                if (r < 0)
-                                        return r;
+                                if (statx(inode_fd, "", AT_EMPTY_PATH, statx_mask | STATX_TYPE, &sx) < 0)
+                                        return -errno;
 
                                 assert(sx.stx_mask & STATX_TYPE);
                                 sx_valid = true;
@@ -311,15 +308,15 @@ int recurse_dir(
 
                         } else if (statx_mask != 0 || (de->entries[i]->d_type == DT_UNKNOWN && (flags & RECURSE_DIR_ENSURE_TYPE))) {
 
-                                r = statx_fallback(dir_fd, de->entries[i]->d_name, AT_SYMLINK_NOFOLLOW, statx_mask | STATX_TYPE, &sx);
-                                if (r == -ENOENT) /* Vanished by now? Go for next file immediately */
-                                        continue;
-                                if (r < 0) {
-                                        log_debug_errno(r, "Failed to stat directory entry '%s': %m", p);
+                                if (statx(dir_fd, de->entries[i]->d_name, AT_SYMLINK_NOFOLLOW, statx_mask | STATX_TYPE, &sx) < 0) {
+                                        if (errno == ENOENT) /* Vanished by now? Go for next file immediately */
+                                                continue;
+
+                                        log_debug_errno(errno, "Failed to stat directory entry '%s': %m", p);
 
-                                        assert(-r <= RECURSE_DIR_SKIP_STAT_INODE_ERROR_MAX - RECURSE_DIR_SKIP_STAT_INODE_ERROR_BASE);
+                                        assert(errno <= RECURSE_DIR_SKIP_STAT_INODE_ERROR_MAX - RECURSE_DIR_SKIP_STAT_INODE_ERROR_BASE);
 
-                                        r = func(RECURSE_DIR_SKIP_STAT_INODE_ERROR_BASE + -r,
+                                        r = func(RECURSE_DIR_SKIP_STAT_INODE_ERROR_BASE + errno,
                                                  p,
                                                  dir_fd,
                                                  -1,
index 687b7b2ddcf901eeed8b8bc39a7fc341a6434e48..8ae588e2e111782f72eec2b47f336587354a287b 100644 (file)
@@ -483,76 +483,6 @@ bool statx_mount_same(const struct statx *a, const struct statx *b) {
                 a->stx_dev_minor == b->stx_dev_minor;
 }
 
-static bool is_statx_fatal_error(int err, int flags) {
-        assert(err < 0);
-
-        /* If statx() is not supported or if we see EPERM (which might indicate seccomp filtering or so),
-         * let's do a fallback. Note that on EACCES we'll not fall back, since that is likely an indication of
-         * fs access issues, which we should propagate. */
-        if (ERRNO_IS_NOT_SUPPORTED(err) || err == -EPERM)
-                return false;
-
-        /* When unsupported flags are specified, glibc's fallback function returns -EINVAL.
-         * See statx_generic() in glibc. */
-        if (err != -EINVAL)
-                return true;
-
-        if ((flags & ~(AT_EMPTY_PATH | AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | AT_STATX_SYNC_AS_STAT)) != 0)
-                return false; /* Unsupported flags are specified. Let's try to use our implementation. */
-
-        return true;
-}
-
-int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx) {
-        static bool avoid_statx = false;
-        struct stat st;
-        int r;
-
-        if (!avoid_statx) {
-                r = RET_NERRNO(statx(dfd, path, flags, mask, sx));
-                if (r >= 0 || is_statx_fatal_error(r, flags))
-                        return r;
-
-                avoid_statx = true;
-        }
-
-        /* Only do fallback if fstatat() supports the flag too, or if it's one of the sync flags, which are
-         * OK to ignore */
-        if ((flags & ~(AT_EMPTY_PATH|AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW|
-                      AT_STATX_SYNC_AS_STAT|AT_STATX_FORCE_SYNC|AT_STATX_DONT_SYNC)) != 0)
-                return -EOPNOTSUPP;
-
-        if (fstatat(dfd, path, &st, flags & (AT_EMPTY_PATH|AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW)) < 0)
-                return -errno;
-
-        *sx = (struct statx) {
-                .stx_mask = STATX_TYPE|STATX_MODE|
-                STATX_NLINK|STATX_UID|STATX_GID|
-                STATX_ATIME|STATX_MTIME|STATX_CTIME|
-                STATX_INO|STATX_SIZE|STATX_BLOCKS,
-                .stx_blksize = st.st_blksize,
-                .stx_nlink = st.st_nlink,
-                .stx_uid = st.st_uid,
-                .stx_gid = st.st_gid,
-                .stx_mode = st.st_mode,
-                .stx_ino = st.st_ino,
-                .stx_size = st.st_size,
-                .stx_blocks = st.st_blocks,
-                .stx_rdev_major = major(st.st_rdev),
-                .stx_rdev_minor = minor(st.st_rdev),
-                .stx_dev_major = major(st.st_dev),
-                .stx_dev_minor = minor(st.st_dev),
-                .stx_atime.tv_sec = st.st_atim.tv_sec,
-                .stx_atime.tv_nsec = st.st_atim.tv_nsec,
-                .stx_mtime.tv_sec = st.st_mtim.tv_sec,
-                .stx_mtime.tv_nsec = st.st_mtim.tv_nsec,
-                .stx_ctime.tv_sec = st.st_ctim.tv_sec,
-                .stx_ctime.tv_nsec = st.st_ctim.tv_nsec,
-        };
-
-        return 0;
-}
-
 int xstatfsat(int dir_fd, const char *path, struct statfs *ret) {
         _cleanup_close_ int fd = -EBADF;
 
index f7c926e9f8024e0f449ff90702accb24a9f1eef6..e4fd4221390b0e820e7f9802d4a10f0f343e1a19 100644 (file)
@@ -91,8 +91,6 @@ bool stat_inode_unmodified(const struct stat *a, const struct stat *b);
 bool statx_inode_same(const struct statx *a, const struct statx *b);
 bool statx_mount_same(const struct statx *a, const struct statx *b);
 
-int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx);
-
 int xstatfsat(int dir_fd, const char *path, struct statfs *ret);
 
 static inline usec_t statx_timestamp_load(const struct statx_timestamp *ts) {
index 9b6517f53d3770d66ff46746844882bb333c99b0..e0550a7a09c4dac4db912b378e3f1a90c155cd8c 100644 (file)
@@ -290,11 +290,11 @@ static int verify_fsroot_dir(
         if (r < 0 && r != -EADDRNOTAVAIL)
                 return log_error_errno(r, "Failed to extract filename of %s: %m", path);
 
-        r = statx_fallback(dir_fd, strempty(f), AT_SYMLINK_NOFOLLOW|(isempty(f) ? AT_EMPTY_PATH : 0),
-                           STATX_TYPE|STATX_INO|STATX_MNT_ID, &sxa);
-        if (r < 0)
-                return log_full_errno((searching && r == -ENOENT) ||
-                                      (unprivileged_mode && ERRNO_IS_PRIVILEGE(r)) ? LOG_DEBUG : LOG_ERR, r,
+        if (statx(dir_fd, strempty(f),
+                  AT_SYMLINK_NOFOLLOW|(isempty(f) ? AT_EMPTY_PATH : 0),
+                  STATX_TYPE|STATX_INO|STATX_MNT_ID, &sxa) < 0)
+                return log_full_errno((searching && errno == ENOENT) ||
+                                      (unprivileged_mode && ERRNO_IS_PRIVILEGE(errno)) ? LOG_DEBUG : LOG_ERR, errno,
                                       "Failed to determine block device node of \"%s\": %m", path);
 
         assert(S_ISDIR(sxa.stx_mode)); /* We used O_DIRECTORY above, when opening, so this must hold */
@@ -314,9 +314,8 @@ static int verify_fsroot_dir(
         }
 
         /* Now let's look at the parent */
-        r = statx_fallback(dir_fd, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sxb);
-        if (r < 0)
-                return log_full_errno(unprivileged_mode && ERRNO_IS_PRIVILEGE(r) ? LOG_DEBUG : LOG_ERR, r,
+        if (statx(dir_fd, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sxb) < 0)
+                return log_full_errno(unprivileged_mode && ERRNO_IS_PRIVILEGE(errno) ? LOG_DEBUG : LOG_ERR, errno,
                                       "Failed to determine block device node of parent of \"%s\": %m", path);
 
         if (statx_inode_same(&sxa, &sxb)) /* for the root dir inode nr for both inodes will be the same */
index b3b50fc315d92103a776f62a0272f10fdd65526f..231247adbf77bd8d6ad70df55b0fedcd2d6b2887 100644 (file)
@@ -591,17 +591,15 @@ static int opendir_and_stat(
                 return 0;
         }
 
-        r = statx_fallback(dirfd(d), "", AT_EMPTY_PATH, STATX_MODE|STATX_INO|STATX_ATIME|STATX_MTIME, &sx1);
-        if (r < 0)
-                return log_error_errno(r, "statx(%s) failed: %m", path);
+        if (statx(dirfd(d), "", AT_EMPTY_PATH, STATX_MODE|STATX_INO|STATX_ATIME|STATX_MTIME, &sx1) < 0)
+                return log_error_errno(errno, "statx(%s) failed: %m", path);
 
         if (FLAGS_SET(sx1.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT))
                 *ret_mountpoint = FLAGS_SET(sx1.stx_attributes, STATX_ATTR_MOUNT_ROOT);
         else {
                 struct statx sx2;
-                r = statx_fallback(dirfd(d), "..", 0, STATX_INO, &sx2);
-                if (r < 0)
-                        return log_error_errno(r, "statx(%s/..) failed: %m", path);
+                if (statx(dirfd(d), "..", 0, STATX_INO, &sx2) < 0)
+                        return log_error_errno(errno, "statx(%s/..) failed: %m", path);
 
                 *ret_mountpoint = !statx_mount_same(&sx1, &sx2);
         }
@@ -707,16 +705,15 @@ static int dir_cleanup(
                  * st_dev. */
 
                 struct statx sx;
-                r = statx_fallback(
-                                dirfd(d), de->d_name,
-                                AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT,
-                                STATX_TYPE|STATX_MODE|STATX_UID|STATX_ATIME|STATX_MTIME|STATX_CTIME|STATX_BTIME,
-                                &sx);
-                if (r == -ENOENT)
-                        continue;
-                if (r < 0) {
+                if (statx(dirfd(d), de->d_name,
+                          AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT,
+                          STATX_TYPE|STATX_MODE|STATX_UID|STATX_ATIME|STATX_MTIME|STATX_CTIME|STATX_BTIME,
+                          &sx) < 0) {
+                        if (errno == ENOENT)
+                                continue;
+
                         /* FUSE, NFS mounts, SELinux might return EACCES */
-                        log_full_errno(r == -EACCES ? LOG_DEBUG : LOG_ERR, r,
+                        log_full_errno(errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
                                        "statx(%s/%s) failed: %m", p, de->d_name);
                         continue;
                 }