]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
mountpoint-util: use new kernel 5.8 statx() API for determining mnt_id
authorLennart Poettering <lennart@poettering.net>
Wed, 5 Aug 2020 21:28:21 +0000 (23:28 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 19 Aug 2020 08:08:24 +0000 (10:08 +0200)
The kernel finally has a proper API to determine the mnt_id of a file.
Let's use it.

This adds support for the STATX_MNT_ID field of statx(), added in
kernel 5.8.

src/basic/missing_stat.h
src/basic/missing_syscall.h
src/basic/mountpoint-util.c

index 5116206a2e53cdb265b7facbd21584ff908b7489..291ae721a4a9999b4abb08cc9b0bf39eb1ea9a3f 100644 (file)
@@ -8,38 +8,47 @@
 #include <linux/stat.h>
 #endif
 
-/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
+/* Thew newest definition we are aware of (fa2fcf4f1df1559a0a4ee0f46915b496cc2ebf60; 5.8) */
+#define STATX_DEFINITION {                      \
+        __u32 stx_mask;                         \
+        __u32 stx_blksize;                      \
+        __u64 stx_attributes;                   \
+        __u32 stx_nlink;                        \
+        __u32 stx_uid;                          \
+        __u32 stx_gid;                          \
+        __u16 stx_mode;                         \
+        __u16 __spare0[1];                      \
+        __u64 stx_ino;                          \
+        __u64 stx_size;                         \
+        __u64 stx_blocks;                       \
+        __u64 stx_attributes_mask;              \
+        struct statx_timestamp stx_atime;       \
+        struct statx_timestamp stx_btime;       \
+        struct statx_timestamp stx_ctime;       \
+        struct statx_timestamp stx_mtime;       \
+        __u32 stx_rdev_major;                   \
+        __u32 stx_rdev_minor;                   \
+        __u32 stx_dev_major;                    \
+        __u32 stx_dev_minor;                    \
+        __u64 stx_mnt_id;                       \
+        __u64 __spare2;                         \
+        __u64 __spare3[12];                     \
+}
+
 #if !HAVE_STRUCT_STATX
 struct statx_timestamp {
         __s64 tv_sec;
         __u32 tv_nsec;
         __s32 __reserved;
 };
-struct statx {
-        __u32 stx_mask;
-        __u32 stx_blksize;
-        __u64 stx_attributes;
-        __u32 stx_nlink;
-        __u32 stx_uid;
-        __u32 stx_gid;
-        __u16 stx_mode;
-        __u16 __spare0[1];
-        __u64 stx_ino;
-        __u64 stx_size;
-        __u64 stx_blocks;
-        __u64 stx_attributes_mask;
-        struct statx_timestamp stx_atime;
-        struct statx_timestamp stx_btime;
-        struct statx_timestamp stx_ctime;
-        struct statx_timestamp stx_mtime;
-        __u32 stx_rdev_major;
-        __u32 stx_rdev_minor;
-        __u32 stx_dev_major;
-        __u32 stx_dev_minor;
-        __u64 __spare2[14];
-};
+
+struct statx STATX_DEFINITION;
 #endif
 
+/* Always define the newest version we are aware of as a distinct type, so that we can use it even if glibc
+ * defines an older definition */
+struct new_statx STATX_DEFINITION;
+
 /* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
 #ifndef STATX_BTIME
 #define STATX_BTIME 0x00000800U
@@ -49,3 +58,8 @@ struct statx {
 #ifndef AT_STATX_DONT_SYNC
 #define AT_STATX_DONT_SYNC 0x4000
 #endif
+
+/* fa2fcf4f1df1559a0a4ee0f46915b496cc2ebf60 (5.8) */
+#ifndef STATX_MNT_ID
+#define STATX_MNT_ID 0x00001000U
+#endif
index 501c4d811cc2b3e020bdb269ee7202e4daae2413..b633ea4541f7adda86b7395b0eca6cfa8057d020 100644 (file)
@@ -482,7 +482,7 @@ static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flag
 #  endif
 }
 
-#  define statx missing_statx
+#  define statx(dfd, filename, flags, mask, buffer) missing_statx(dfd, filename, flags, mask, buffer)
 #endif
 
 #if !HAVE_SET_MEMPOLICY
index 1e1c21f35d1bd073da0eb41d603e5e2b1685094c..bb6b6f064d451f19eb1655138d17468f07b8ce16 100644 (file)
@@ -8,6 +8,8 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
+#include "missing_stat.h"
+#include "missing_syscall.h"
 #include "mountpoint-util.h"
 #include "parse-util.h"
 #include "path-util.h"
@@ -283,8 +285,29 @@ int path_is_mount_point(const char *t, const char *root, int flags) {
 }
 
 int path_get_mnt_id(const char *path, int *ret) {
+        union {
+                struct statx sx;
+                struct new_statx nsx;
+        } buf
+#if HAS_FEATURE_MEMORY_SANITIZER
+                = {}
+#  warning "Explicitly initializing struct statx, to work around msan limitation. Please remove as soon as msan has been updated to not require this."
+#endif
+                ;
         int r;
 
+        if (statx(AT_FDCWD, path, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT, STATX_MNT_ID, &buf.sx) < 0) {
+                if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
+                        return -errno;
+
+                /* Fall back to name_to_handle_at() and then fdinfo if statx is not supported or we lack
+                 * privileges */
+
+        } else if (FLAGS_SET(buf.nsx.stx_mask, STATX_MNT_ID)) {
+                *ret = buf.nsx.stx_mnt_id;
+                return 0;
+        }
+
         r = name_to_handle_at_loop(AT_FDCWD, path, NULL, ret, 0);
         if (IN_SET(r, -EOPNOTSUPP, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL)) /* kernel/fs don't support this, or seccomp blocks access, or untriggered mount, or name_to_handle_at() is flaky */
                 return fd_fdinfo_mnt_id(AT_FDCWD, path, 0, ret);