diff options
author | David Howells <dhowells@redhat.com> | 2011-01-14 14:10:03 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-01-15 20:07:48 -0500 |
commit | ea5b778a8b98c85a87d66bf844904f9c3802b869 (patch) | |
tree | baa56cbe1a907d76341f2cad53e16569cc1d3288 /fs/namespace.c | |
parent | ab90911ff90cdab59b31c045c3f0ae480d14f29d (diff) |
Unexport do_add_mount() and add in follow_automount(), not ->d_automount()
Unexport do_add_mount() and make ->d_automount() return the vfsmount to be
added rather than calling do_add_mount() itself. follow_automount() will then
do the addition.
This slightly complicates things as ->d_automount() normally wants to add the
new vfsmount to an expiration list and start an expiration timer. The problem
with that is that the vfsmount will be deleted if it has a refcount of 1 and
the timer will not repeat if the expiration list is empty.
To this end, we require the vfsmount to be returned from d_automount() with a
refcount of (at least) 2. One of these refs will be dropped unconditionally.
In addition, follow_automount() must get a 3rd ref around the call to
do_add_mount() lest it eat a ref and return an error, leaving the mount we
have open to being expired as we would otherwise have only 1 ref on it.
d_automount() should also add the the vfsmount to the expiration list (by
calling mnt_set_expiry()) and start the expiration timer before returning, if
this mechanism is to be used. The vfsmount will be unlinked from the
expiration list by follow_automount() if do_add_mount() fails.
This patch also fixes the call to do_add_mount() for AFS to propagate the mount
flags from the parent vfsmount.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index d94ccd6ddafd..bfcb701f9490 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1925,15 +1925,14 @@ static int do_new_mount(struct path *path, char *type, int flags, | |||
1925 | if (IS_ERR(mnt)) | 1925 | if (IS_ERR(mnt)) |
1926 | return PTR_ERR(mnt); | 1926 | return PTR_ERR(mnt); |
1927 | 1927 | ||
1928 | return do_add_mount(mnt, path, mnt_flags, NULL); | 1928 | return do_add_mount(mnt, path, mnt_flags); |
1929 | } | 1929 | } |
1930 | 1930 | ||
1931 | /* | 1931 | /* |
1932 | * add a mount into a namespace's mount tree | 1932 | * add a mount into a namespace's mount tree |
1933 | * - provide the option of adding the new mount to an expiration list | 1933 | * - this unconditionally eats one of the caller's references to newmnt. |
1934 | */ | 1934 | */ |
1935 | int do_add_mount(struct vfsmount *newmnt, struct path *path, | 1935 | int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags) |
1936 | int mnt_flags, struct list_head *fslist) | ||
1937 | { | 1936 | { |
1938 | int err; | 1937 | int err; |
1939 | 1938 | ||
@@ -1963,9 +1962,6 @@ int do_add_mount(struct vfsmount *newmnt, struct path *path, | |||
1963 | if ((err = graft_tree(newmnt, path))) | 1962 | if ((err = graft_tree(newmnt, path))) |
1964 | goto unlock; | 1963 | goto unlock; |
1965 | 1964 | ||
1966 | if (fslist) /* add to the specified expiration list */ | ||
1967 | list_add_tail(&newmnt->mnt_expire, fslist); | ||
1968 | |||
1969 | up_write(&namespace_sem); | 1965 | up_write(&namespace_sem); |
1970 | return 0; | 1966 | return 0; |
1971 | 1967 | ||
@@ -1975,7 +1971,36 @@ unlock: | |||
1975 | return err; | 1971 | return err; |
1976 | } | 1972 | } |
1977 | 1973 | ||
1978 | EXPORT_SYMBOL_GPL(do_add_mount); | 1974 | /** |
1975 | * mnt_set_expiry - Put a mount on an expiration list | ||
1976 | * @mnt: The mount to list. | ||
1977 | * @expiry_list: The list to add the mount to. | ||
1978 | */ | ||
1979 | void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list) | ||
1980 | { | ||
1981 | down_write(&namespace_sem); | ||
1982 | br_write_lock(vfsmount_lock); | ||
1983 | |||
1984 | list_add_tail(&mnt->mnt_expire, expiry_list); | ||
1985 | |||
1986 | br_write_unlock(vfsmount_lock); | ||
1987 | up_write(&namespace_sem); | ||
1988 | } | ||
1989 | EXPORT_SYMBOL(mnt_set_expiry); | ||
1990 | |||
1991 | /* | ||
1992 | * Remove a vfsmount from any expiration list it may be on | ||
1993 | */ | ||
1994 | void mnt_clear_expiry(struct vfsmount *mnt) | ||
1995 | { | ||
1996 | if (!list_empty(&mnt->mnt_expire)) { | ||
1997 | down_write(&namespace_sem); | ||
1998 | br_write_lock(vfsmount_lock); | ||
1999 | list_del_init(&mnt->mnt_expire); | ||
2000 | br_write_unlock(vfsmount_lock); | ||
2001 | up_write(&namespace_sem); | ||
2002 | } | ||
2003 | } | ||
1979 | 2004 | ||
1980 | /* | 2005 | /* |
1981 | * process a list of expirable mountpoints with the intent of discarding any | 2006 | * process a list of expirable mountpoints with the intent of discarding any |