stat-util: teach statx_mount_same() STATX_MNT_ID_UNIQUE

So far statx_mount_same() assumed STATX_MNT_ID_UNIQUE didn't exist.
However it does exist, hence do something useful if we see it set. Note
that this creates a certain ambiguity: if we compare one statx struct
with STATX_MNT_ID_UNIQUE and one without it (but with the regular mnt
id), then we cnanot really come to a clear conclusion, hence need to
introduce a third, unknown state.

Note that we don't request STATX_MNT_ID_UNIQUE yet wherever we call
statx_mount_same(). THis will be added in a later commit.
This commit is contained in:
Lennart Poettering
2026-03-03 08:48:01 +01:00
parent 6d61bb671d
commit 2e9208199f
5 changed files with 29 additions and 12 deletions
+14 -5
View File
@@ -379,11 +379,20 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
* root tree we operate in is allowed, where an inode is moved up the tree while we
* look at it, and thus get the current path wrong and think we are deeper down than
* we actually are. */
if (FLAGS_SET(flags, CHASE_AT_RESOLVE_IN_ROOT) &&
(empty_or_root(done) || (statx_inode_same(&stx, &root_stx) && statx_mount_same(&stx, &root_stx)))) {
if (FLAGS_SET(flags, CHASE_STEP))
goto chased_one;
continue;
if (FLAGS_SET(flags, CHASE_AT_RESOLVE_IN_ROOT)) {
bool is_root = empty_or_root(done);
if (!is_root && statx_inode_same(&stx, &root_stx)) {
r = statx_mount_same(&stx, &root_stx);
if (r < 0)
return r;
is_root = r > 0;
}
if (is_root) {
if (FLAGS_SET(flags, CHASE_STEP))
goto chased_one;
continue;
}
}
fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH|O_DIRECTORY);
+5 -1
View File
@@ -1094,7 +1094,11 @@ int fds_inode_and_mount_same(int fd1, int fd2) {
if (r < 0)
return r;
return statx_inode_same(&sx1, &sx2) && statx_mount_same(&sx1, &sx2);
r = statx_mount_same(&sx1, &sx2);
if (r <= 0)
return r;
return statx_inode_same(&sx1, &sx2);
}
int resolve_xat_fdroot(int *fd, const char **path, char **ret_buffer) {
+5 -4
View File
@@ -675,14 +675,15 @@ bool statx_inode_same(const struct statx *a, const struct statx *b) {
a->stx_ino == b->stx_ino;
}
bool statx_mount_same(const struct statx *a, const struct statx *b) {
int statx_mount_same(const struct statx *a, const struct statx *b) {
if (!statx_is_set(a) || !statx_is_set(b))
return false;
assert(FLAGS_SET(a->stx_mask, STATX_MNT_ID));
assert(FLAGS_SET(b->stx_mask, STATX_MNT_ID));
if ((FLAGS_SET(a->stx_mask, STATX_MNT_ID) && FLAGS_SET(b->stx_mask, STATX_MNT_ID)) ||
(FLAGS_SET(a->stx_mask, STATX_MNT_ID_UNIQUE) && FLAGS_SET(b->stx_mask, STATX_MNT_ID_UNIQUE)))
return a->stx_mnt_id == b->stx_mnt_id;
return a->stx_mnt_id == b->stx_mnt_id;
return -ENODATA;
}
usec_t statx_timestamp_load(const struct statx_timestamp *ts) {
+1 -1
View File
@@ -110,7 +110,7 @@ bool stat_inode_same(const struct stat *a, const struct stat *b);
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_mount_same(const struct statx *a, const struct statx *b);
int xstatfsat(int dir_fd, const char *path, struct statfs *ret);