From: Yu Watanabe Date: Mon, 5 Jan 2026 04:24:40 +0000 (+0900) Subject: fd-util,mountpoint-util: STATX_MNT_ID is supported since kernel 5.10 X-Git-Tag: v260-rc1~408^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7ecfa87c56f2523141e11694577df8a380694598;p=thirdparty%2Fsystemd.git fd-util,mountpoint-util: STATX_MNT_ID is supported since kernel 5.10 Our baseline on kernel is 5.10, hence we can assume it works. --- diff --git a/README b/README index ce25c1e3a1e..718a02d0871 100644 --- a/README +++ b/README @@ -52,6 +52,7 @@ REQUIREMENTS: BPF links and the BPF LSM hook ≥ 5.8 for LOOP_CONFIGURE and STATX_ATTR_MOUNT_ROOT ≥ 5.9 for close_range() + ≥ 5.10 for STATX_MNT_ID ⛔ Kernel versions below 5.10 ("minimum baseline") are not supported at all, and are missing required functionality as listed above. diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c index 834b162c47d..fb4262e62b3 100644 --- a/src/basic/fd-util.c +++ b/src/basic/fd-util.c @@ -16,7 +16,6 @@ #include "format-util.h" #include "fs-util.h" #include "log.h" -#include "mountpoint-util.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" @@ -1119,7 +1118,6 @@ int path_is_root_at(int dir_fd, const char *path) { int fds_are_same_mount(int fd1, int fd2) { struct statx sx1 = {}, sx2 = {}; /* explicitly initialize the struct to make msan silent. */ - int r; assert(fd1 >= 0); assert(fd2 >= 0); @@ -1130,39 +1128,7 @@ int fds_are_same_mount(int fd1, int fd2) { 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)) - return false; - - /* Note, statx() does not provide the mount ID and path_get_mnt_id_at() does not work when an old - * kernel is used. In that case, let's assume that we do not have such spurious mount points in an - * early boot stage, and silently skip the following check. */ - - if (!FLAGS_SET(sx1.stx_mask, STATX_MNT_ID)) { - int mntid; - - r = path_get_mnt_id_at_fallback(fd1, "", &mntid); - if (r < 0) - return r; - assert(mntid >= 0); - - sx1.stx_mnt_id = mntid; - sx1.stx_mask |= STATX_MNT_ID; - } - - if (!FLAGS_SET(sx2.stx_mask, STATX_MNT_ID)) { - int mntid; - - r = path_get_mnt_id_at_fallback(fd2, "", &mntid); - if (r < 0) - return r; - assert(mntid >= 0); - - sx2.stx_mnt_id = mntid; - sx2.stx_mask |= STATX_MNT_ID; - } - - return statx_mount_same(&sx1, &sx2); + return statx_inode_same(&sx1, &sx2) && statx_mount_same(&sx1, &sx2); } char* format_proc_fd_path(char buf[static PROC_FD_PATH_MAX], int fd) { diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c index 1453340c55a..35bf3bdfccd 100644 --- a/src/basic/mountpoint-util.c +++ b/src/basic/mountpoint-util.c @@ -13,10 +13,8 @@ #include "log.h" #include "mountpoint-util.h" #include "nulstr-util.h" -#include "parse-util.h" #include "path-util.h" #include "stat-util.h" -#include "stdio-util.h" #include "string-util.h" #include "strv.h" @@ -135,34 +133,6 @@ int name_to_handle_at_try_fid( return name_to_handle_at_loop(fd, path, ret_handle, ret_mnt_id, flags & ~AT_HANDLE_FID); } -static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *ret_mnt_id) { - char path[STRLEN("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)]; - _cleanup_close_ int subfd = -EBADF; - int r; - - assert((flags & ~(AT_SYMLINK_FOLLOW|AT_EMPTY_PATH)) == 0); - assert(ret_mnt_id); - - if ((flags & AT_EMPTY_PATH) && isempty(filename)) - xsprintf(path, "/proc/self/fdinfo/%i", fd); - else { - subfd = openat(fd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_FOLLOW ? 0 : O_NOFOLLOW)); - if (subfd < 0) - return -errno; - - xsprintf(path, "/proc/self/fdinfo/%i", subfd); - } - - _cleanup_free_ char *p = NULL; - r = get_proc_field(path, "mnt_id", &p); - if (r == -ENOENT) - return -EBADF; - if (r < 0) - return r; - - return safe_atoi(p, ret_mnt_id); -} - bool file_handle_equal(const struct file_handle *a, const struct file_handle *b) { if (a == b) return true; @@ -238,21 +208,9 @@ int path_is_mount_point_full(const char *path, const char *root, int flags) { return is_mount_point_at(dir_fd, /* path= */ NULL, flags); } -int path_get_mnt_id_at_fallback(int dir_fd, const char *path, int *ret) { - int r; - - assert(dir_fd >= 0 || dir_fd == AT_FDCWD); - assert(ret); - - r = name_to_handle_at_loop(dir_fd, path, NULL, ret, isempty(path) ? AT_EMPTY_PATH : 0); - if (r >= 0 || is_name_to_handle_at_fatal_error(r)) - return r; - - return fd_fdinfo_mnt_id(dir_fd, path, isempty(path) ? AT_EMPTY_PATH : 0, ret); -} - int path_get_mnt_id_at(int dir_fd, const char *path, int *ret) { struct statx sx; + int r; assert(dir_fd >= 0 || dir_fd == AT_FDCWD); assert(ret); @@ -266,12 +224,12 @@ int path_get_mnt_id_at(int dir_fd, const char *path, int *ret) { &sx) < 0) return -errno; - if (FLAGS_SET(sx.stx_mask, STATX_MNT_ID)) { - *ret = sx.stx_mnt_id; - return 0; - } + r = statx_warn_mount_id(&sx, LOG_DEBUG); + if (r < 0) + return r; - return path_get_mnt_id_at_fallback(dir_fd, path, ret); + *ret = sx.stx_mnt_id; + return 0; } bool fstype_is_network(const char *fstype) { diff --git a/src/basic/mountpoint-util.h b/src/basic/mountpoint-util.h index 206815277bc..899e9635d19 100644 --- a/src/basic/mountpoint-util.h +++ b/src/basic/mountpoint-util.h @@ -39,7 +39,6 @@ int name_to_handle_at_try_fid(int fd, const char *path, struct file_handle **ret bool file_handle_equal(const struct file_handle *a, const struct file_handle *b); -int path_get_mnt_id_at_fallback(int dir_fd, const char *path, int *ret); int path_get_mnt_id_at(int dir_fd, const char *path, int *ret); static inline int path_get_mnt_id(const char *path, int *ret) { return path_get_mnt_id_at(AT_FDCWD, path, ret); diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 791e99d978f..b7016ed6b7c 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -475,13 +475,10 @@ bool statx_mount_same(const struct statx *a, const struct statx *b) { if (!statx_is_set(a) || !statx_is_set(b)) return false; - /* if we have the mount ID, that's all we need */ - if (FLAGS_SET(a->stx_mask, STATX_MNT_ID) && FLAGS_SET(b->stx_mask, STATX_MNT_ID)) - return a->stx_mnt_id == b->stx_mnt_id; + assert(FLAGS_SET(a->stx_mask, STATX_MNT_ID)); + assert(FLAGS_SET(b->stx_mask, STATX_MNT_ID)); - /* Otherwise, major/minor of backing device must match */ - return a->stx_dev_major == b->stx_dev_major && - a->stx_dev_minor == b->stx_dev_minor; + return a->stx_mnt_id == b->stx_mnt_id; } int xstatfsat(int dir_fd, const char *path, struct statfs *ret) { @@ -583,3 +580,14 @@ int statx_warn_mount_root(const struct statx *sx, int log_level) { return 0; } + +int statx_warn_mount_id(const struct statx *sx, int log_level) { + assert(sx); + + /* The STATX_MNT_ID flag is supported since kernel v5.10. */ + if (!FLAGS_SET(sx->stx_mask, STATX_MNT_ID)) + return log_full_errno(log_level, SYNTHETIC_ERRNO(ENOSYS), + "statx() does not support STATX_MNT_ID, running on an old kernel?"); + + return 0; +} diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h index a0a4489f74c..11d0fdc7ff7 100644 --- a/src/basic/stat-util.h +++ b/src/basic/stat-util.h @@ -119,3 +119,4 @@ static inline bool inode_type_can_hardlink(mode_t m) { } int statx_warn_mount_root(const struct statx *sx, int log_level); +int statx_warn_mount_id(const struct statx *sx, int log_level);