Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1a2c409 authored by Miklos Szeredi's avatar Miklos Szeredi Committed by Al Viro
Browse files

[patch 5/7] vfs: mountinfo: allow using process root



Allow /proc/<pid>/mountinfo to use the root of <pid> to calculate
mountpoints.

 - move definition of 'struct proc_mounts' to <linux/mnt_namespace.h>
 - add the process's namespace and root to this structure
 - pass a pointer to 'struct proc_mounts' into seq_operations

In addition the following cleanups are made:

 - use a common open function for /proc/<pid>/{mounts,mountstat}
 - surround namespace.c part of these proc files with #ifdef CONFIG_PROC_FS
 - make the seq_operations structures const

Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 719f5d7f
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -724,20 +724,21 @@ void save_mount_options(struct super_block *sb, char *options)
}
EXPORT_SYMBOL(save_mount_options);

#ifdef CONFIG_PROC_FS
/* iterator */
static void *m_start(struct seq_file *m, loff_t *pos)
{
	struct mnt_namespace *n = m->private;
	struct proc_mounts *p = m->private;

	down_read(&namespace_sem);
	return seq_list_start(&n->list, *pos);
	return seq_list_start(&p->ns->list, *pos);
}

static void *m_next(struct seq_file *m, void *v, loff_t *pos)
{
	struct mnt_namespace *n = m->private;
	struct proc_mounts *p = m->private;

	return seq_list_next(v, &n->list, pos);
	return seq_list_next(v, &p->ns->list, pos);
}

static void m_stop(struct seq_file *m, void *v)
@@ -794,7 +795,7 @@ static int show_vfsmnt(struct seq_file *m, void *v)
	return err;
}

struct seq_operations mounts_op = {
const struct seq_operations mounts_op = {
	.start	= m_start,
	.next	= m_next,
	.stop	= m_stop,
@@ -833,12 +834,13 @@ static int show_vfsstat(struct seq_file *m, void *v)
	return err;
}

struct seq_operations mountstats_op = {
const struct seq_operations mountstats_op = {
	.start	= m_start,
	.next	= m_next,
	.stop	= m_stop,
	.show	= show_vfsstat,
};
#endif  /* CONFIG_PROC_FS */

/**
 * may_umount_tree - check if a mount tree is busy
+51 −57
Original line number Diff line number Diff line
@@ -502,17 +502,14 @@ static const struct inode_operations proc_def_inode_operations = {
	.setattr	= proc_setattr,
};

extern const struct seq_operations mounts_op;
struct proc_mounts {
	struct seq_file m;
	int event;
};

static int mounts_open(struct inode *inode, struct file *file)
static int mounts_open_common(struct inode *inode, struct file *file,
			      const struct seq_operations *op)
{
	struct task_struct *task = get_proc_task(inode);
	struct nsproxy *nsp;
	struct mnt_namespace *ns = NULL;
	struct fs_struct *fs = NULL;
	struct path root;
	struct proc_mounts *p;
	int ret = -EINVAL;

@@ -525,40 +522,61 @@ static int mounts_open(struct inode *inode, struct file *file)
				get_mnt_ns(ns);
		}
		rcu_read_unlock();

		if (ns)
			fs = get_fs_struct(task);
		put_task_struct(task);
	}

	if (ns) {
	if (!ns)
		goto err;
	if (!fs)
		goto err_put_ns;

	read_lock(&fs->lock);
	root = fs->root;
	path_get(&root);
	read_unlock(&fs->lock);
	put_fs_struct(fs);

	ret = -ENOMEM;
	p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
		if (p) {
	if (!p)
		goto err_put_path;

	file->private_data = &p->m;
			ret = seq_open(file, &mounts_op);
			if (!ret) {
				p->m.private = ns;
	ret = seq_open(file, op);
	if (ret)
		goto err_free;

	p->m.private = p;
	p->ns = ns;
	p->root = root;
	p->event = ns->event;

	return 0;
			}

 err_free:
	kfree(p);
		}
 err_put_path:
	path_put(&root);
 err_put_ns:
	put_mnt_ns(ns);
	}
 err:
	return ret;
}

static int mounts_release(struct inode *inode, struct file *file)
{
	struct seq_file *m = file->private_data;
	struct mnt_namespace *ns = m->private;
	put_mnt_ns(ns);
	struct proc_mounts *p = file->private_data;
	path_put(&p->root);
	put_mnt_ns(p->ns);
	return seq_release(inode, file);
}

static unsigned mounts_poll(struct file *file, poll_table *wait)
{
	struct proc_mounts *p = file->private_data;
	struct mnt_namespace *ns = p->m.private;
	struct mnt_namespace *ns = p->ns;
	unsigned res = 0;

	poll_wait(file, &ns->poll, wait);
@@ -573,6 +591,11 @@ static unsigned mounts_poll(struct file *file, poll_table *wait)
	return res;
}

static int mounts_open(struct inode *inode, struct file *file)
{
	return mounts_open_common(inode, file, &mounts_op);
}

static const struct file_operations proc_mounts_operations = {
	.open		= mounts_open,
	.read		= seq_read,
@@ -581,38 +604,9 @@ static const struct file_operations proc_mounts_operations = {
	.poll		= mounts_poll,
};

extern const struct seq_operations mountstats_op;
static int mountstats_open(struct inode *inode, struct file *file)
{
	int ret = seq_open(file, &mountstats_op);

	if (!ret) {
		struct seq_file *m = file->private_data;
		struct nsproxy *nsp;
		struct mnt_namespace *mnt_ns = NULL;
		struct task_struct *task = get_proc_task(inode);

		if (task) {
			rcu_read_lock();
			nsp = task_nsproxy(task);
			if (nsp) {
				mnt_ns = nsp->mnt_ns;
				if (mnt_ns)
					get_mnt_ns(mnt_ns);
			}
			rcu_read_unlock();

			put_task_struct(task);
		}

		if (mnt_ns)
			m->private = mnt_ns;
		else {
			seq_release(inode, file);
			ret = -EINVAL;
		}
	}
	return ret;
	return mounts_open_common(inode, file, &mountstats_op);
}

static const struct file_operations proc_mountstats_operations = {
+11 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include <linux/mount.h>
#include <linux/sched.h>
#include <linux/nsproxy.h>
#include <linux/seq_file.h>

struct mnt_namespace {
	atomic_t		count;
@@ -14,6 +15,13 @@ struct mnt_namespace {
	int event;
};

struct proc_mounts {
	struct seq_file m; /* must be the first element */
	struct mnt_namespace *ns;
	struct path root;
	int event;
};

extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
		struct fs_struct *);
extern void __put_mnt_ns(struct mnt_namespace *ns);
@@ -37,5 +45,8 @@ static inline void get_mnt_ns(struct mnt_namespace *ns)
	atomic_inc(&ns->count);
}

extern const struct seq_operations mounts_op;
extern const struct seq_operations mountstats_op;

#endif
#endif