diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-01-17 01:35:23 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-01-17 01:35:23 -0500 |
commit | 19a167af7c97248ec646552ebc9140bc6aa3552a (patch) | |
tree | a521153c80fa6e40b2b4983c5bba21c2e96d1864 | |
parent | e78bf5e6cbe837daa6ab628a5f679548742994d3 (diff) |
Take the completion of automount into new helper
... and shift it from namei.c to namespace.c
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/internal.h | 1 | ||||
-rw-r--r-- | fs/namei.c | 31 | ||||
-rw-r--r-- | fs/namespace.c | 33 |
3 files changed, 39 insertions, 26 deletions
diff --git a/fs/internal.h b/fs/internal.h index 12ccb86edef7..e8a0b245177d 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -70,6 +70,7 @@ extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, | |||
70 | extern void release_mounts(struct list_head *); | 70 | extern void release_mounts(struct list_head *); |
71 | extern void umount_tree(struct vfsmount *, int, struct list_head *); | 71 | extern void umount_tree(struct vfsmount *, int, struct list_head *); |
72 | extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); | 72 | extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); |
73 | extern int finish_automount(struct vfsmount *, struct path *); | ||
73 | extern int do_add_mount(struct vfsmount *, struct path *, int); | 74 | extern int do_add_mount(struct vfsmount *, struct path *, int); |
74 | extern void mnt_clear_expiry(struct vfsmount *); | 75 | extern void mnt_clear_expiry(struct vfsmount *); |
75 | 76 | ||
diff --git a/fs/namei.c b/fs/namei.c index 8f7b41a14882..b753192d8c3f 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -923,37 +923,13 @@ static int follow_automount(struct path *path, unsigned flags, | |||
923 | if (!mnt) /* mount collision */ | 923 | if (!mnt) /* mount collision */ |
924 | return 0; | 924 | return 0; |
925 | 925 | ||
926 | /* The new mount record should have at least 2 refs to prevent it being | 926 | err = finish_automount(mnt, path); |
927 | * expired before we get a chance to add it | ||
928 | */ | ||
929 | BUG_ON(mnt_get_count(mnt) < 2); | ||
930 | |||
931 | if (mnt->mnt_sb == path->mnt->mnt_sb && | ||
932 | mnt->mnt_root == path->dentry) { | ||
933 | mnt_clear_expiry(mnt); | ||
934 | mntput(mnt); | ||
935 | mntput(mnt); | ||
936 | return -ELOOP; | ||
937 | } | ||
938 | 927 | ||
939 | /* We need to add the mountpoint to the parent. The filesystem may | ||
940 | * have placed it on an expiry list, and so we need to make sure it | ||
941 | * won't be expired under us if do_add_mount() fails (do_add_mount() | ||
942 | * will eat a reference unconditionally). | ||
943 | */ | ||
944 | mntget(mnt); | ||
945 | err = do_add_mount(mnt, path, path->mnt->mnt_flags | MNT_SHRINKABLE); | ||
946 | switch (err) { | 928 | switch (err) { |
947 | case -EBUSY: | 929 | case -EBUSY: |
948 | /* Someone else made a mount here whilst we were busy */ | 930 | /* Someone else made a mount here whilst we were busy */ |
949 | err = 0; | 931 | return 0; |
950 | default: | ||
951 | mnt_clear_expiry(mnt); | ||
952 | mntput(mnt); | ||
953 | mntput(mnt); | ||
954 | return err; | ||
955 | case 0: | 932 | case 0: |
956 | mntput(mnt); | ||
957 | dput(path->dentry); | 933 | dput(path->dentry); |
958 | if (*need_mntput) | 934 | if (*need_mntput) |
959 | mntput(path->mnt); | 935 | mntput(path->mnt); |
@@ -961,7 +937,10 @@ static int follow_automount(struct path *path, unsigned flags, | |||
961 | path->dentry = dget(mnt->mnt_root); | 937 | path->dentry = dget(mnt->mnt_root); |
962 | *need_mntput = true; | 938 | *need_mntput = true; |
963 | return 0; | 939 | return 0; |
940 | default: | ||
941 | return err; | ||
964 | } | 942 | } |
943 | |||
965 | } | 944 | } |
966 | 945 | ||
967 | /* | 946 | /* |
diff --git a/fs/namespace.c b/fs/namespace.c index 9f544f35ed34..bec51e4e0549 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1895,6 +1895,39 @@ static int do_new_mount(struct path *path, char *type, int flags, | |||
1895 | return do_add_mount(mnt, path, mnt_flags); | 1895 | return do_add_mount(mnt, path, mnt_flags); |
1896 | } | 1896 | } |
1897 | 1897 | ||
1898 | int finish_automount(struct vfsmount *m, struct path *path) | ||
1899 | { | ||
1900 | int err; | ||
1901 | /* The new mount record should have at least 2 refs to prevent it being | ||
1902 | * expired before we get a chance to add it | ||
1903 | */ | ||
1904 | BUG_ON(mnt_get_count(m) < 2); | ||
1905 | |||
1906 | if (m->mnt_sb == path->mnt->mnt_sb && | ||
1907 | m->mnt_root == path->dentry) { | ||
1908 | mnt_clear_expiry(m); | ||
1909 | mntput(m); | ||
1910 | mntput(m); | ||
1911 | return -ELOOP; | ||
1912 | } | ||
1913 | |||
1914 | /* We need to add the mountpoint to the parent. The filesystem may | ||
1915 | * have placed it on an expiry list, and so we need to make sure it | ||
1916 | * won't be expired under us if do_add_mount() fails (do_add_mount() | ||
1917 | * will eat a reference unconditionally). | ||
1918 | */ | ||
1919 | mntget(m); | ||
1920 | err = do_add_mount(m, path, path->mnt->mnt_flags | MNT_SHRINKABLE); | ||
1921 | if (err) { | ||
1922 | mnt_clear_expiry(m); | ||
1923 | mntput(m); | ||
1924 | mntput(m); | ||
1925 | } else { | ||
1926 | mntput(m); | ||
1927 | } | ||
1928 | return err; | ||
1929 | } | ||
1930 | |||
1898 | /* | 1931 | /* |
1899 | * add a mount into a namespace's mount tree | 1932 | * add a mount into a namespace's mount tree |
1900 | * - this unconditionally eats one of the caller's references to newmnt. | 1933 | * - this unconditionally eats one of the caller's references to newmnt. |