summaryrefslogtreecommitdiff
path: root/fs/namespace.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-17 11:00:09 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-17 11:00:09 -0800
commit235646a486d10891bd86af28d8eac75d9f22bd2d (patch)
tree72308e6d2d7c936d00907689a2749715873d5f1b /fs/namespace.c
parentaf575e2d2e09517a8190f1b425453cc3e0102f6c (diff)
parentecf5632dd189ab4c366cef853d6e5fe7adfe52e5 (diff)
downloadlinux-235646a486d10891bd86af28d8eac75d9f22bd2d.tar.gz
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: fs: fix address space warnings in ioctl_fiemap() aio: check return value of create_workqueue() hpfs_setattr error case avoids unlock_kernel compat: copy missing fields in compat_statfs64 to user compat: update comment of compat statfs syscalls compat: remove unnecessary assignment in compat_rw_copy_check_uvector() fs: FS_POSIX_ACL does not depend on BLOCK fs: Remove unlikely() from fget_light() fs: Remove unlikely() from fput_light() fallocate should be a file operation make the feature checks in ->fallocate future proof staging: smbfs building fix tidy up around finish_automount() don't drop newmnt on error in do_add_mount() Take the completion of automount into new helper
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c63
1 files changed, 40 insertions, 23 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 9f544f35ed34..7b0b95371696 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1872,6 +1872,8 @@ out:
return err;
}
+static int do_add_mount(struct vfsmount *, struct path *, int);
+
/*
* create a new mount for userspace and request it to be added into the
* namespace's tree
@@ -1880,6 +1882,7 @@ static int do_new_mount(struct path *path, char *type, int flags,
int mnt_flags, char *name, void *data)
{
struct vfsmount *mnt;
+ int err;
if (!type)
return -EINVAL;
@@ -1892,14 +1895,47 @@ static int do_new_mount(struct path *path, char *type, int flags,
if (IS_ERR(mnt))
return PTR_ERR(mnt);
- return do_add_mount(mnt, path, mnt_flags);
+ err = do_add_mount(mnt, path, mnt_flags);
+ if (err)
+ mntput(mnt);
+ return err;
+}
+
+int finish_automount(struct vfsmount *m, struct path *path)
+{
+ int err;
+ /* The new mount record should have at least 2 refs to prevent it being
+ * expired before we get a chance to add it
+ */
+ BUG_ON(mnt_get_count(m) < 2);
+
+ if (m->mnt_sb == path->mnt->mnt_sb &&
+ m->mnt_root == path->dentry) {
+ err = -ELOOP;
+ goto fail;
+ }
+
+ err = do_add_mount(m, path, path->mnt->mnt_flags | MNT_SHRINKABLE);
+ if (!err)
+ return 0;
+fail:
+ /* remove m from any expiration list it may be on */
+ if (!list_empty(&m->mnt_expire)) {
+ down_write(&namespace_sem);
+ br_write_lock(vfsmount_lock);
+ list_del_init(&m->mnt_expire);
+ br_write_unlock(vfsmount_lock);
+ up_write(&namespace_sem);
+ }
+ mntput(m);
+ mntput(m);
+ return err;
}
/*
* add a mount into a namespace's mount tree
- * - this unconditionally eats one of the caller's references to newmnt.
*/
-int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags)
+static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags)
{
int err;
@@ -1926,15 +1962,10 @@ int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags)
goto unlock;
newmnt->mnt_flags = mnt_flags;
- if ((err = graft_tree(newmnt, path)))
- goto unlock;
-
- up_write(&namespace_sem);
- return 0;
+ err = graft_tree(newmnt, path);
unlock:
up_write(&namespace_sem);
- mntput(newmnt);
return err;
}
@@ -1956,20 +1987,6 @@ void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list)
EXPORT_SYMBOL(mnt_set_expiry);
/*
- * Remove a vfsmount from any expiration list it may be on
- */
-void mnt_clear_expiry(struct vfsmount *mnt)
-{
- if (!list_empty(&mnt->mnt_expire)) {
- down_write(&namespace_sem);
- br_write_lock(vfsmount_lock);
- list_del_init(&mnt->mnt_expire);
- br_write_unlock(vfsmount_lock);
- up_write(&namespace_sem);
- }
-}
-
-/*
* process a list of expirable mountpoints with the intent of discarding any
* mountpoints that aren't in use and haven't been touched since last we came
* here