Print the mnt_id in current mount namespace

Submitted by Chen, Hu on Oct. 17, 2019, 7:02 a.m.

Details

Message ID 20191017070228.21470-2-hu1.chen@intel.com
State New
Series "Print the mnt_id in current mount namespace"
Headers show

Commit Message

Chen, Hu Oct. 17, 2019, 7:02 a.m.
Consdier the below scenarios
1. Open some files
2. unshare -m to enter a new mount namespace
3. Now the files opened in step 1 still point to mnt_id in old namespace.

This patch will print the corresponding mnt_id in current namespace.

Signed-off-by: Chen, Hu <hu1.chen@intel.com>

Patch hide | download patch | download mbox

diff --git a/fs/mount.h b/fs/mount.h
index 711a4093e475..6bbfc2b3b8ba 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -153,3 +153,5 @@  static inline bool is_anon_ns(struct mnt_namespace *ns)
 {
 	return ns->seq == 0;
 }
+
+extern struct mount *lookup_mirror_mnt(const struct mount *mnt);
diff --git a/fs/namespace.c b/fs/namespace.c
index fe0e9e1410fe..6184234868b6 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -683,6 +683,35 @@  bool __is_local_mountpoint(struct dentry *dentry)
 	return is_covered;
 }
 
+/*
+ * lookup_mirror_mnt - Return @mnt's mirror mount in the current/local mount
+ * namespace. If mirror isn't found, just return NULL.
+ */
+struct mount *lookup_mirror_mnt(const struct mount *mnt)
+{
+	struct mnt_namespace *ns = current->nsproxy->mnt_ns;
+	struct mount *mnt_local;
+	bool is_matched = false;
+
+	/* mnt belongs to current namesapce */
+	if (mnt->mnt_ns == ns)
+		return mnt;
+
+	down_read(&namespace_sem);
+	list_for_each_entry(mnt_local, &ns->list, mnt_list) {
+		struct super_block *sb = mnt->mnt.mnt_sb;
+		struct super_block *sb_local = mnt_local->mnt.mnt_sb;
+		if ( MAJOR(sb->s_dev) == MAJOR(sb_local->s_dev) &&
+		     MINOR(sb->s_dev) == MINOR(sb_local->s_dev)) {
+			is_matched = true;
+			break;
+		}
+	}
+	up_read(&namespace_sem);
+
+	return is_matched ? mnt_local : NULL;
+}
+
 static struct mountpoint *lookup_mountpoint(struct dentry *dentry)
 {
 	struct hlist_head *chain = mp_hash(dentry);
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index 81882a13212d..3f9f4ac28e0d 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -23,6 +23,7 @@  static int seq_show(struct seq_file *m, void *v)
 	int f_flags = 0, ret = -ENOENT;
 	struct file *file = NULL;
 	struct task_struct *task;
+	struct mount *mount = NULL;
 
 	task = get_proc_task(m->private);
 	if (!task)
@@ -53,9 +54,16 @@  static int seq_show(struct seq_file *m, void *v)
 	if (ret)
 		return ret;
 
-	seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
+	/* After unshare -m, real_mount(file->f_path.mnt) is not meaningful in
+	 * current mount namesapce. We want to know the mnt_id in current mount
+	 * namespace */
+	mount = lookup_mirror_mnt(real_mount(file->f_path.mnt));
+	if (!mount)
+		mount = real_mount(file->f_path.mnt);
+
+	seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\nmnt_devname:\t%s\n",
 		   (long long)file->f_pos, f_flags,
-		   real_mount(file->f_path.mnt)->mnt_id);
+		   mount->mnt_id, mount->mnt_devname);
 
 	show_fd_locks(m, file, files);
 	if (seq_has_overflowed(m))