From: Karel Zak Date: Thu, 25 Jun 2026 10:32:31 +0000 (+0200) Subject: libmount: add mnt_fs_fetch_ids() and populate uniq_id for utab X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1cb24d37de96f32596164ce738713c0c04086044;p=thirdparty%2Futil-linux.git libmount: add mnt_fs_fetch_ids() and populate uniq_id for utab Add mnt_fs_fetch_ids() helper that fetches mount IDs from the kernel via statx(). It prefers STATX_MNT_ID_UNIQUE and falls back to the old STATX_MNT_ID on older kernels. Accepts an optional fd argument; when fd < 0 it falls back to path-based lookup via fs->target. Use it in hook_create_mount() (new mount API) with fd_tree for robust fd-based ID, and in hook_mount() (legacy mount(2)) after reopen_target_fd with fd_target when available. This ensures utab entries contain UNIQID, which is needed for reliable utab merging with listmount-based tables. Signed-off-by: Karel Zak --- diff --git a/libmount/src/fs.c b/libmount/src/fs.c index a0d18a4f9..8da98cc84 100644 --- a/libmount/src/fs.c +++ b/libmount/src/fs.c @@ -1533,6 +1533,45 @@ int mnt_fs_set_uniq_id(struct libmnt_fs *fs, uint64_t id) return 0; } +/* + * Fetch mount IDs from kernel via statx(). Prefers unique ID, falls back + * to old ID on old kernels. Uses @fd (AT_EMPTY_PATH) if >= 0, otherwise + * uses fs->target path. + * + * Returns: 0 on success, <0 on error. + */ +int mnt_fs_fetch_ids(struct libmnt_fs *fs, int fd) +{ + uint64_t uniq_id = 0; + int id = 0, rc; + + if (!fs) + return -EINVAL; + if (fd < 0 && !mnt_fs_get_target(fs)) + return -EINVAL; + + if (fd >= 0) + rc = mnt_id_from_fd(fd, &uniq_id, NULL); + else + rc = mnt_id_from_path(mnt_fs_get_target(fs), &uniq_id, NULL); + + if (rc == 0 && uniq_id > 0) { + fs->uniq_id = uniq_id; + return 0; + } + + /* fallback to old mount ID */ + if (fd >= 0) + rc = mnt_id_from_fd(fd, NULL, &id); + else + rc = mnt_id_from_path(mnt_fs_get_target(fs), NULL, &id); + + if (rc == 0) + fs->id = id; + + return rc; +} + /** * mnt_fs_get_parent_id: * @fs: /proc/self/mountinfo entry diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c index 1dab62c68..acd0df027 100644 --- a/libmount/src/hook_mount.c +++ b/libmount/src/hook_mount.c @@ -323,24 +323,22 @@ static int hook_create_mount(struct libmnt_context *cxt, /* cleanup after fail (libmount may only try the FS type) */ close_sysapi_fds(api); -#if defined(HAVE_STATX) && defined(HAVE_STRUCT_STATX) && defined(HAVE_STRUCT_STATX_STX_MNT_ID) if (!rc && cxt->fs) { - struct statx st; - - rc = statx(api->fd_tree, "", AT_EMPTY_PATH, STATX_MNT_ID, &st); - if (rc == 0) { - cxt->fs->id = (int) st.stx_mnt_id; - if (cxt->update) { - struct libmnt_fs *fs = mnt_update_get_fs(cxt->update); - if (fs) - fs->id = cxt->fs->id; + mnt_fs_fetch_ids(cxt->fs, api->fd_tree); + + if ((cxt->fs->id || cxt->fs->uniq_id) && cxt->update) { + struct libmnt_fs *fs = mnt_update_get_fs(cxt->update); + if (fs) { + fs->id = cxt->fs->id; + fs->uniq_id = cxt->fs->uniq_id; } } } -#endif done: - DBG_OBJ(HOOK, hs, ul_debug("create FS done [rc=%d, id=%d]", rc, cxt->fs ? cxt->fs->id : -1)); + DBG_OBJ(HOOK, hs, ul_debug("create FS done [rc=%d, id=%d, uniq=%" PRIu64 "]", + rc, cxt->fs ? cxt->fs->id : -1, + cxt->fs ? cxt->fs->uniq_id : (uint64_t) 0)); return rc; } diff --git a/libmount/src/hook_mount_legacy.c b/libmount/src/hook_mount_legacy.c index 86b1c9f06..0327db4c2 100644 --- a/libmount/src/hook_mount_legacy.c +++ b/libmount/src/hook_mount_legacy.c @@ -251,10 +251,25 @@ static int hook_mount(struct libmnt_context *cxt, else mnt_fs_mark_attached(cxt->fs); + cxt->syscall_status = 0; + /* re-open to point to the mounted filesystem root */ rc = mnt_context_reopen_target_fd(cxt); - cxt->syscall_status = 0; + /* Fetch mount IDs for utab. Note that IDs are not 100% robust + * with mount(2) -- another process could overmount the target + * between mount(2) and our statx() call. */ + if (rc == 0 && cxt->fs && cxt->update && mnt_update_is_ready(cxt->update)) { + mnt_fs_fetch_ids(cxt->fs, cxt->fd_target); + if (cxt->fs->id || cxt->fs->uniq_id) { + struct libmnt_fs *fs = mnt_update_get_fs(cxt->update); + if (fs) { + fs->id = cxt->fs->id; + fs->uniq_id = cxt->fs->uniq_id; + } + } + } + return rc; } diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 01af14f3f..3f5a93d94 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -140,6 +140,7 @@ extern int mnt_tmptgt_unshare(int *old_ns_fd); extern int mnt_tmptgt_cleanup(int old_ns_fd); extern int mnt_id_from_fd(int fd, uint64_t *uniq_id, int *id); +extern int mnt_fs_fetch_ids(struct libmnt_fs *fs, int fd); /* tab.c */ extern int is_mountinfo(struct libmnt_table *tb);