Commit 19a167af7c97248ec646552ebc9140bc6aa3552a
1 parent
e78bf5e6cb
Exists in
master
and in
7 other branches
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>
Showing 3 changed files with 39 additions and 26 deletions Side-by-side Diff
fs/internal.h
... | ... | @@ -70,6 +70,7 @@ |
70 | 70 | extern void release_mounts(struct list_head *); |
71 | 71 | extern void umount_tree(struct vfsmount *, int, struct list_head *); |
72 | 72 | extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); |
73 | +extern int finish_automount(struct vfsmount *, struct path *); | |
73 | 74 | extern int do_add_mount(struct vfsmount *, struct path *, int); |
74 | 75 | extern void mnt_clear_expiry(struct vfsmount *); |
75 | 76 |
fs/namei.c
... | ... | @@ -923,37 +923,13 @@ |
923 | 923 | if (!mnt) /* mount collision */ |
924 | 924 | return 0; |
925 | 925 | |
926 | - /* The new mount record should have at least 2 refs to prevent it being | |
927 | - * expired before we get a chance to add it | |
928 | - */ | |
929 | - BUG_ON(mnt_get_count(mnt) < 2); | |
926 | + err = finish_automount(mnt, path); | |
930 | 927 | |
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 | - | |
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 | 928 | switch (err) { |
947 | 929 | case -EBUSY: |
948 | 930 | /* Someone else made a mount here whilst we were busy */ |
949 | - err = 0; | |
950 | - default: | |
951 | - mnt_clear_expiry(mnt); | |
952 | - mntput(mnt); | |
953 | - mntput(mnt); | |
954 | - return err; | |
931 | + return 0; | |
955 | 932 | case 0: |
956 | - mntput(mnt); | |
957 | 933 | dput(path->dentry); |
958 | 934 | if (*need_mntput) |
959 | 935 | mntput(path->mnt); |
960 | 936 | |
... | ... | @@ -961,7 +937,10 @@ |
961 | 937 | path->dentry = dget(mnt->mnt_root); |
962 | 938 | *need_mntput = true; |
963 | 939 | return 0; |
940 | + default: | |
941 | + return err; | |
964 | 942 | } |
943 | + | |
965 | 944 | } |
966 | 945 | |
967 | 946 | /* |
fs/namespace.c
... | ... | @@ -1895,6 +1895,39 @@ |
1895 | 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 | 1932 | * add a mount into a namespace's mount tree |
1900 | 1933 | * - this unconditionally eats one of the caller's references to newmnt. |