Commit 0714a533 authored by Al Viro's avatar Al Viro
Browse files

vfs: now it can be done - make mnt_parent point to struct mount



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 3376f34f
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -2452,6 +2452,7 @@ static int prepend_path(const struct path *path,
{
	struct dentry *dentry = path->dentry;
	struct vfsmount *vfsmnt = path->mnt;
	struct mount *mnt = real_mount(vfsmnt);
	bool slash = false;
	int error = 0;

@@ -2460,12 +2461,12 @@ static int prepend_path(const struct path *path,
		struct dentry * parent;

		if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
			struct mount *mnt = real_mount(vfsmnt);
			/* Global root? */
			if (!mnt_has_parent(mnt))
				goto global_root;
			dentry = vfsmnt->mnt_mountpoint;
			vfsmnt = mnt->mnt_parent;
			dentry = mnt->mnt.mnt_mountpoint;
			mnt = mnt->mnt_parent;
			vfsmnt = &mnt->mnt;
			continue;
		}
		parent = dentry->d_parent;
+2 −2
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@

struct mount {
	struct list_head mnt_hash;
	struct vfsmount *mnt_parent;
	struct mount *mnt_parent;
	struct vfsmount mnt;
};

@@ -13,7 +13,7 @@ static inline struct mount *real_mount(struct vfsmount *mnt)

static inline int mnt_has_parent(struct mount *mnt)
{
	return &mnt->mnt != mnt->mnt_parent;
	return mnt != mnt->mnt_parent;
}

extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
+13 −11
Original line number Diff line number Diff line
@@ -677,36 +677,38 @@ follow_link(struct path *link, struct nameidata *nd, void **p)

static int follow_up_rcu(struct path *path)
{
	struct vfsmount *parent;
	struct mount *mnt = real_mount(path->mnt);
	struct mount *parent;
	struct dentry *mountpoint;

	parent = real_mount(path->mnt)->mnt_parent;
	if (parent == path->mnt)
	parent = mnt->mnt_parent;
	if (&parent->mnt == path->mnt)
		return 0;
	mountpoint = path->mnt->mnt_mountpoint;
	mountpoint = mnt->mnt.mnt_mountpoint;
	path->dentry = mountpoint;
	path->mnt = parent;
	path->mnt = &parent->mnt;
	return 1;
}

int follow_up(struct path *path)
{
	struct vfsmount *parent;
	struct mount *mnt = real_mount(path->mnt);
	struct mount *parent;
	struct dentry *mountpoint;

	br_read_lock(vfsmount_lock);
	parent = real_mount(path->mnt)->mnt_parent;
	if (parent == path->mnt) {
	parent = mnt->mnt_parent;
	if (&parent->mnt == path->mnt) {
		br_read_unlock(vfsmount_lock);
		return 0;
	}
	mntget(parent);
	mountpoint = dget(path->mnt->mnt_mountpoint);
	mntget(&parent->mnt);
	mountpoint = dget(mnt->mnt.mnt_mountpoint);
	br_read_unlock(vfsmount_lock);
	dput(path->dentry);
	path->dentry = mountpoint;
	mntput(path->mnt);
	path->mnt = parent;
	path->mnt = &parent->mnt;
	return 1;
}

+26 −26
Original line number Diff line number Diff line
@@ -476,7 +476,7 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry,
		if (tmp == head)
			break;
		p = list_entry(tmp, struct mount, mnt_hash);
		if (p->mnt_parent == mnt && p->mnt.mnt_mountpoint == dentry) {
		if (&p->mnt_parent->mnt == mnt && p->mnt.mnt_mountpoint == dentry) {
			found = p;
			break;
		}
@@ -558,8 +558,8 @@ static void dentry_reset_mounted(struct dentry *dentry)
static void detach_mnt(struct mount *mnt, struct path *old_path)
{
	old_path->dentry = mnt->mnt.mnt_mountpoint;
	old_path->mnt = mnt->mnt_parent;
	mnt->mnt_parent = &mnt->mnt;
	old_path->mnt = &mnt->mnt_parent->mnt;
	mnt->mnt_parent = mnt;
	mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root;
	list_del_init(&mnt->mnt.mnt_child);
	list_del_init(&mnt->mnt_hash);
@@ -572,7 +572,7 @@ static void detach_mnt(struct mount *mnt, struct path *old_path)
void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry,
			struct mount *child_mnt)
{
	child_mnt->mnt_parent = mntget(mnt);
	child_mnt->mnt_parent = real_mount(mntget(mnt));
	child_mnt->mnt.mnt_mountpoint = dget(dentry);
	spin_lock(&dentry->d_lock);
	dentry->d_flags |= DCACHE_MOUNTED;
@@ -610,12 +610,12 @@ static inline void __mnt_make_shortterm(struct vfsmount *mnt)
 */
static void commit_tree(struct mount *mnt)
{
	struct vfsmount *parent = mnt->mnt_parent;
	struct mount *parent = mnt->mnt_parent;
	struct vfsmount *m;
	LIST_HEAD(head);
	struct mnt_namespace *n = parent->mnt_ns;
	struct mnt_namespace *n = parent->mnt.mnt_ns;

	BUG_ON(parent == &mnt->mnt);
	BUG_ON(parent == mnt);

	list_add_tail(&head, &mnt->mnt.mnt_list);
	list_for_each_entry(m, &head, mnt_list) {
@@ -626,8 +626,8 @@ static void commit_tree(struct mount *mnt)
	list_splice(&head, n->list.prev);

	list_add_tail(&mnt->mnt_hash, mount_hashtable +
				hash(parent, mnt->mnt.mnt_mountpoint));
	list_add_tail(&mnt->mnt.mnt_child, &parent->mnt_mounts);
				hash(&parent->mnt, mnt->mnt.mnt_mountpoint));
	list_add_tail(&mnt->mnt.mnt_child, &parent->mnt.mnt_mounts);
	touch_mnt_namespace(n);
}

@@ -639,9 +639,9 @@ static struct mount *next_mnt(struct mount *p, struct vfsmount *root)
			if (&p->mnt == root)
				return NULL;
			next = p->mnt.mnt_child.next;
			if (next != &p->mnt_parent->mnt_mounts)
			if (next != &p->mnt_parent->mnt.mnt_mounts)
				break;
			p = real_mount(p->mnt_parent);
			p = p->mnt_parent;
		}
	}
	return list_entry(next, struct mount, mnt.mnt_child);
@@ -682,7 +682,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
	mnt->mnt.mnt_root = root;
	mnt->mnt.mnt_sb = root->d_sb;
	mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root;
	mnt->mnt_parent = &mnt->mnt;
	mnt->mnt_parent = mnt;
	return &mnt->mnt;
}
EXPORT_SYMBOL_GPL(vfs_kern_mount);
@@ -710,7 +710,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
		mnt->mnt.mnt_sb = sb;
		mnt->mnt.mnt_root = dget(root);
		mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root;
		mnt->mnt_parent = &mnt->mnt;
		mnt->mnt_parent = mnt;

		if (flag & CL_SLAVE) {
			list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave_list);
@@ -1027,7 +1027,7 @@ static int show_mountinfo(struct seq_file *m, void *v)
	struct path root = p->root;
	int err = 0;

	seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, r->mnt_parent->mnt_id,
	seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, r->mnt_parent->mnt.mnt_id,
		   MAJOR(sb->s_dev), MINOR(sb->s_dev));
	if (sb->s_op->show_path)
		err = sb->s_op->show_path(m, mnt);
@@ -1202,9 +1202,9 @@ void release_mounts(struct list_head *head)

			br_write_lock(vfsmount_lock);
			dentry = mnt->mnt.mnt_mountpoint;
			m = mnt->mnt_parent;
			m = &mnt->mnt_parent->mnt;
			mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root;
			mnt->mnt_parent = &mnt->mnt;
			mnt->mnt_parent = mnt;
			m->mnt_ghosts--;
			br_write_unlock(vfsmount_lock);
			dput(dentry);
@@ -1237,7 +1237,7 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill)
		__mnt_make_shortterm(&p->mnt);
		list_del_init(&p->mnt.mnt_child);
		if (mnt_has_parent(p)) {
			p->mnt_parent->mnt_ghosts++;
			p->mnt_parent->mnt.mnt_ghosts++;
			dentry_reset_mounted(p->mnt.mnt_mountpoint);
		}
		change_mnt_propagation(p, MS_PRIVATE);
@@ -1435,9 +1435,9 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
				s = skip_mnt_tree(s);
				continue;
			}
			while (p != real_mount(s->mnt_parent)) {
				p = real_mount(p->mnt_parent);
				q = real_mount(q->mnt_parent);
			while (p != s->mnt_parent) {
				p = p->mnt_parent;
				q = q->mnt_parent;
			}
			p = s;
			path.mnt = &q->mnt;
@@ -1899,7 +1899,7 @@ static int do_move_mount(struct path *path, char *old_name)
	/*
	 * Don't move a mount residing in a shared parent.
	 */
	if (IS_MNT_SHARED(old->mnt_parent))
	if (IS_MNT_SHARED(&old->mnt_parent->mnt))
		goto out1;
	/*
	 * Don't move a mount tree containing unbindable mounts to a destination
@@ -1909,7 +1909,7 @@ static int do_move_mount(struct path *path, char *old_name)
	    tree_contains_unbindable(old))
		goto out1;
	err = -ELOOP;
	for (p = real_mount(path->mnt); mnt_has_parent(p); p = real_mount(p->mnt_parent))
	for (p = real_mount(path->mnt); mnt_has_parent(p); p = p->mnt_parent)
		if (p == old)
			goto out1;

@@ -2159,7 +2159,7 @@ resume:
	 */
	if (this_parent != parent) {
		next = this_parent->mnt.mnt_child.next;
		this_parent = real_mount(this_parent->mnt_parent);
		this_parent = this_parent->mnt_parent;
		goto resume;
	}
	return found;
@@ -2565,7 +2565,7 @@ bool is_path_reachable(struct mount *mnt, struct dentry *dentry,
{
	while (&mnt->mnt != root->mnt && mnt_has_parent(mnt)) {
		dentry = mnt->mnt.mnt_mountpoint;
		mnt = real_mount(mnt->mnt_parent);
		mnt = mnt->mnt_parent;
	}
	return &mnt->mnt == root->mnt && is_subdir(dentry, root->dentry);
}
@@ -2636,8 +2636,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
	new_mnt = real_mount(new.mnt);
	root_mnt = real_mount(root.mnt);
	if (IS_MNT_SHARED(old.mnt) ||
		IS_MNT_SHARED(new_mnt->mnt_parent) ||
		IS_MNT_SHARED(root_mnt->mnt_parent))
		IS_MNT_SHARED(&new_mnt->mnt_parent->mnt) ||
		IS_MNT_SHARED(&root_mnt->mnt_parent->mnt))
		goto out4;
	if (!check_mnt(root.mnt) || !check_mnt(new.mnt))
		goto out4;
+8 −8
Original line number Diff line number Diff line
@@ -292,10 +292,10 @@ int propagate_mount_busy(struct mount *mnt, int refcnt)
{
	struct vfsmount *m;
	struct mount *child;
	struct vfsmount *parent = mnt->mnt_parent;
	struct mount *parent = mnt->mnt_parent;
	int ret = 0;

	if (&mnt->mnt == parent)
	if (mnt == parent)
		return do_refcount_check(mnt, refcnt);

	/*
@@ -306,8 +306,8 @@ int propagate_mount_busy(struct mount *mnt, int refcnt)
	if (!list_empty(&mnt->mnt.mnt_mounts) || do_refcount_check(mnt, refcnt))
		return 1;

	for (m = propagation_next(parent, parent); m;
	     		m = propagation_next(m, parent)) {
	for (m = propagation_next(&parent->mnt, &parent->mnt); m;
	     		m = propagation_next(m, &parent->mnt)) {
		child = __lookup_mnt(m, mnt->mnt.mnt_mountpoint, 0);
		if (child && list_empty(&child->mnt.mnt_mounts) &&
		    (ret = do_refcount_check(child, 1)))
@@ -322,13 +322,13 @@ int propagate_mount_busy(struct mount *mnt, int refcnt)
 */
static void __propagate_umount(struct mount *mnt)
{
	struct vfsmount *parent = mnt->mnt_parent;
	struct mount *parent = mnt->mnt_parent;
	struct vfsmount *m;

	BUG_ON(parent == &mnt->mnt);
	BUG_ON(parent == mnt);

	for (m = propagation_next(parent, parent); m;
			m = propagation_next(m, parent)) {
	for (m = propagation_next(&parent->mnt, &parent->mnt); m;
			m = propagation_next(m, &parent->mnt)) {

		struct mount *child = __lookup_mnt(m,
					mnt->mnt.mnt_mountpoint, 0);