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
/* 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;
}
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;
}
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);