]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fd-util,mountpoint-util: STATX_MNT_ID is supported since kernel 5.10
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 5 Jan 2026 04:24:40 +0000 (13:24 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 13 Jan 2026 01:21:05 +0000 (10:21 +0900)
Our baseline on kernel is 5.10, hence we can assume it works.

README
src/basic/fd-util.c
src/basic/mountpoint-util.c
src/basic/mountpoint-util.h
src/basic/stat-util.c
src/basic/stat-util.h

diff --git a/README b/README
index ce25c1e3a1e53949de3e7901807bb5e192b6d5d2..718a02d0871d410934d02252d55f03ddb24599ff 100644 (file)
--- 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.
index 834b162c47d74aa4ba5935adf99a358cd93eae26..fb4262e62b3983b8ab0bb2150d5e9bf9e232e6f0 100644 (file)
@@ -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) {
index 1453340c55a845c1f3fdc7f8f02e8117fe5ceccb..35bf3bdfccd7555baaac728472cc554e34548678 100644 (file)
 #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) {
index 206815277bcdc60f8832975823dbed44835d482d..899e9635d198dd48e72ad17962d7fe978bdf077c 100644 (file)
@@ -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);
index 791e99d978f5a95f5bcee7cd4ead72b2eada9d90..b7016ed6b7c7cf35f35b9f04c51ed59cce526bdd 100644 (file)
@@ -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;
+}
index a0a4489f74c73c29716d40ffe78bfc71b0a55a0b..11d0fdc7ff7352fc10dfa438c605eadbc035f487 100644 (file)
@@ -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);