diff options
Diffstat (limited to 'fs/namespace.c')
| -rw-r--r-- | fs/namespace.c | 32 | 
1 files changed, 32 insertions, 0 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index e5e1c7d1839..6d3a1963879 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2483,11 +2483,43 @@ struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)  		__mnt_make_longterm(mnt);  		new_ns->root = mnt;  		list_add(&new_ns->list, &new_ns->root->mnt_list); +	} else { +		mntput(mnt);  	}  	return new_ns;  }  EXPORT_SYMBOL(create_mnt_ns); +struct dentry *mount_subtree(struct vfsmount *mnt, const char *name) +{ +	struct mnt_namespace *ns; +	struct super_block *s; +	struct path path; +	int err; + +	ns = create_mnt_ns(mnt); +	if (IS_ERR(ns)) +		return ERR_CAST(ns); + +	err = vfs_path_lookup(mnt->mnt_root, mnt, +			name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path); + +	put_mnt_ns(ns); + +	if (err) +		return ERR_PTR(err); + +	/* trade a vfsmount reference for active sb one */ +	s = path.mnt->mnt_sb; +	atomic_inc(&s->s_active); +	mntput(path.mnt); +	/* lock the sucker */ +	down_write(&s->s_umount); +	/* ... and return the root of (sub)tree on it */ +	return path.dentry; +} +EXPORT_SYMBOL(mount_subtree); +  SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,  		char __user *, type, unsigned long, flags, void __user *, data)  {  |