diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-01-17 01:41:58 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-01-17 01:41:58 -0500 |
commit | 15f9a3f3e199647fe0cac19302c5033cf031372d (patch) | |
tree | 38a39510439f2913dbdfcfd2de4ffacc8214875d /fs | |
parent | 19a167af7c97248ec646552ebc9140bc6aa3552a (diff) |
don't drop newmnt on error in do_add_mount()
That gets rid of the kludge in finish_automount() - we need
to keep refcount on the vfsmount as-is until we evict it from
expiry list.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/namespace.c | 16 |
1 files changed, 5 insertions, 11 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index bec51e4e0549..31aefc8e5fa6 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1880,6 +1880,7 @@ static int do_new_mount(struct path *path, char *type, int flags, | |||
1880 | int mnt_flags, char *name, void *data) | 1880 | int mnt_flags, char *name, void *data) |
1881 | { | 1881 | { |
1882 | struct vfsmount *mnt; | 1882 | struct vfsmount *mnt; |
1883 | int err; | ||
1883 | 1884 | ||
1884 | if (!type) | 1885 | if (!type) |
1885 | return -EINVAL; | 1886 | return -EINVAL; |
@@ -1892,7 +1893,10 @@ static int do_new_mount(struct path *path, char *type, int flags, | |||
1892 | if (IS_ERR(mnt)) | 1893 | if (IS_ERR(mnt)) |
1893 | return PTR_ERR(mnt); | 1894 | return PTR_ERR(mnt); |
1894 | 1895 | ||
1895 | return do_add_mount(mnt, path, mnt_flags); | 1896 | err = do_add_mount(mnt, path, mnt_flags); |
1897 | if (err) | ||
1898 | mntput(mnt); | ||
1899 | return err; | ||
1896 | } | 1900 | } |
1897 | 1901 | ||
1898 | int finish_automount(struct vfsmount *m, struct path *path) | 1902 | int finish_automount(struct vfsmount *m, struct path *path) |
@@ -1911,26 +1915,17 @@ int finish_automount(struct vfsmount *m, struct path *path) | |||
1911 | return -ELOOP; | 1915 | return -ELOOP; |
1912 | } | 1916 | } |
1913 | 1917 | ||
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); | 1918 | err = do_add_mount(m, path, path->mnt->mnt_flags | MNT_SHRINKABLE); |
1921 | if (err) { | 1919 | if (err) { |
1922 | mnt_clear_expiry(m); | 1920 | mnt_clear_expiry(m); |
1923 | mntput(m); | 1921 | mntput(m); |
1924 | mntput(m); | 1922 | mntput(m); |
1925 | } else { | ||
1926 | mntput(m); | ||
1927 | } | 1923 | } |
1928 | return err; | 1924 | return err; |
1929 | } | 1925 | } |
1930 | 1926 | ||
1931 | /* | 1927 | /* |
1932 | * add a mount into a namespace's mount tree | 1928 | * add a mount into a namespace's mount tree |
1933 | * - this unconditionally eats one of the caller's references to newmnt. | ||
1934 | */ | 1929 | */ |
1935 | int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags) | 1930 | int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags) |
1936 | { | 1931 | { |
@@ -1967,7 +1962,6 @@ int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags) | |||
1967 | 1962 | ||
1968 | unlock: | 1963 | unlock: |
1969 | up_write(&namespace_sem); | 1964 | up_write(&namespace_sem); |
1970 | mntput(newmnt); | ||
1971 | return err; | 1965 | return err; |
1972 | } | 1966 | } |
1973 | 1967 | ||