From: Yu Watanabe Date: Fri, 28 Feb 2025 10:19:23 +0000 (+0900) Subject: stat-util: drop statx_fallback() X-Git-Tag: v258-rc1~1216^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d5ddc0e0d3a2f869e6d18ff78390ab16a8f9de98;p=thirdparty%2Fsystemd.git stat-util: drop statx_fallback() Now both our required baseline of glibc and kernel support statx. --- diff --git a/src/basic/dirent-util.c b/src/basic/dirent-util.c index 51db9820f9c..e25097d8aee 100644 --- a/src/basic/dirent-util.c +++ b/src/basic/dirent-util.c @@ -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); diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c index 2691210d918..8329c44a56b 100644 --- a/src/basic/fd-util.c +++ b/src/basic/fd-util.c @@ -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)) diff --git a/src/basic/recurse-dir.c b/src/basic/recurse-dir.c index 18e06551681..9612b7c6a50 100644 --- a/src/basic/recurse-dir.c +++ b/src/basic/recurse-dir.c @@ -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, diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 687b7b2ddcf..8ae588e2e11 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -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; diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h index f7c926e9f80..e4fd4221390 100644 --- a/src/basic/stat-util.h +++ b/src/basic/stat-util.h @@ -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) { diff --git a/src/shared/find-esp.c b/src/shared/find-esp.c index 9b6517f53d3..e0550a7a09c 100644 --- a/src/shared/find-esp.c +++ b/src/shared/find-esp.c @@ -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 */ diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index b3b50fc315d..231247adbf7 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -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; }