Skip to content

Commit 98d2b43

Browse files
Miklos Szeredibrauner
authored andcommitted
add unique mount ID
If a mount is released then its mnt_id can immediately be reused. This is bad news for user interfaces that want to uniquely identify a mount. Implementing a unique mount ID is trivial (use a 64bit counter). Unfortunately userspace assumes 32bit size and would overflow after the counter reaches 2^32. Introduce a new 64bit ID alongside the old one. Initialize the counter to 2^32, this guarantees that the old and new IDs are never mixed up. Signed-off-by: Miklos Szeredi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Ian Kent <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent b85ea95 commit 98d2b43

File tree

4 files changed

+14
-3
lines changed

4 files changed

+14
-3
lines changed

fs/mount.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ struct mount {
7272
struct fsnotify_mark_connector __rcu *mnt_fsnotify_marks;
7373
__u32 mnt_fsnotify_mask;
7474
#endif
75-
int mnt_id; /* mount identifier */
75+
int mnt_id; /* mount identifier, reused */
76+
u64 mnt_id_unique; /* mount ID unique until reboot */
7677
int mnt_group_id; /* peer group identifier */
7778
int mnt_expiry_mark; /* true if marked for expiry */
7879
struct hlist_head mnt_pins;

fs/namespace.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ static u64 event;
6868
static DEFINE_IDA(mnt_id_ida);
6969
static DEFINE_IDA(mnt_group_ida);
7070

71+
/* Don't allow confusion with old 32bit mount ID */
72+
static atomic64_t mnt_id_ctr = ATOMIC64_INIT(1ULL << 32);
73+
7174
static struct hlist_head *mount_hashtable __ro_after_init;
7275
static struct hlist_head *mountpoint_hashtable __ro_after_init;
7376
static struct kmem_cache *mnt_cache __ro_after_init;
@@ -131,6 +134,7 @@ static int mnt_alloc_id(struct mount *mnt)
131134
if (res < 0)
132135
return res;
133136
mnt->mnt_id = res;
137+
mnt->mnt_id_unique = atomic64_inc_return(&mnt_id_ctr);
134138
return 0;
135139
}
136140

fs/stat.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,13 @@ static int vfs_statx(int dfd, struct filename *filename, int flags,
243243

244244
error = vfs_getattr(&path, stat, request_mask, flags);
245245

246-
stat->mnt_id = real_mount(path.mnt)->mnt_id;
247-
stat->result_mask |= STATX_MNT_ID;
246+
if (request_mask & STATX_MNT_ID_UNIQUE) {
247+
stat->mnt_id = real_mount(path.mnt)->mnt_id_unique;
248+
stat->result_mask |= STATX_MNT_ID_UNIQUE;
249+
} else {
250+
stat->mnt_id = real_mount(path.mnt)->mnt_id;
251+
stat->result_mask |= STATX_MNT_ID;
252+
}
248253

249254
if (path.mnt->mnt_root == path.dentry)
250255
stat->attributes |= STATX_ATTR_MOUNT_ROOT;

include/uapi/linux/stat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ struct statx {
154154
#define STATX_BTIME 0x00000800U /* Want/got stx_btime */
155155
#define STATX_MNT_ID 0x00001000U /* Got stx_mnt_id */
156156
#define STATX_DIOALIGN 0x00002000U /* Want/got direct I/O alignment info */
157+
#define STATX_MNT_ID_UNIQUE 0x00004000U /* Want/got extended stx_mount_id */
157158

158159
#define STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */
159160

0 commit comments

Comments
 (0)