summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2008-03-22 05:46:23 +0100
committerAl Viro <viro@zeniv.linux.org.uk>2008-03-28 01:47:58 +0100
commitc35038becad0adb0e25261fff66d85b1a6ddd0c2 (patch)
tree1d375d74ef5b4c3641768697b2ff8f4992916dc5 /fs
parent[PATCH] sanitize locking in mark_mounts_for_expiry() and shrink_submounts() (diff)
downloadlinux-c35038becad0adb0e25261fff66d85b1a6ddd0c2.tar.xz
linux-c35038becad0adb0e25261fff66d85b1a6ddd0c2.zip
[PATCH] do shrink_submounts() for all fs types
... and take it out of ->umount_begin() instances. Call with all locks already taken (by do_umount()) and leave calling release_mounts() to caller (it will do release_mounts() anyway, so we can just put into the same list). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/afs/internal.h1
-rw-r--r--fs/afs/mntpt.c8
-rw-r--r--fs/afs/super.c1
-rw-r--r--fs/cifs/cifs_dfs_ref.c1
-rw-r--r--fs/namespace.c23
-rw-r--r--fs/nfs/super.c2
6 files changed, 10 insertions, 26 deletions
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 5ca3625cd39e..9ba16edc0af2 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -573,7 +573,6 @@ extern const struct file_operations afs_mntpt_file_operations;
extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *);
extern void afs_mntpt_kill_timer(void);
-extern void afs_umount_begin(struct vfsmount *, int);
/*
* proc.c
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index a3510b8ba3e7..2f5503902c37 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -283,11 +283,3 @@ void afs_mntpt_kill_timer(void)
cancel_delayed_work(&afs_mntpt_expiry_timer);
flush_scheduled_work();
}
-
-/*
- * begin unmount by attempting to remove all automounted mountpoints we added
- */
-void afs_umount_begin(struct vfsmount *vfsmnt, int flags)
-{
- shrink_submounts(vfsmnt, &afs_vfsmounts);
-}
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 36bbce45f44b..4b572b801d8d 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -50,7 +50,6 @@ static const struct super_operations afs_super_ops = {
.write_inode = afs_write_inode,
.destroy_inode = afs_destroy_inode,
.clear_inode = afs_clear_inode,
- .umount_begin = afs_umount_begin,
.put_super = afs_put_super,
.show_options = generic_show_options,
};
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index a1a95b027136..56c924033b78 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -33,7 +33,6 @@ void dfs_shrink_umount_helper(struct vfsmount *vfsmnt)
{
mark_mounts_for_expiry(&cifs_dfs_automount_list);
mark_mounts_for_expiry(&cifs_dfs_automount_list);
- shrink_submounts(vfsmnt, &cifs_dfs_automount_list);
}
/**
diff --git a/fs/namespace.c b/fs/namespace.c
index 1c78917ec930..7bd74b25930c 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -581,6 +581,8 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
}
}
+static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts);
+
static int do_umount(struct vfsmount *mnt, int flags)
{
struct super_block *sb = mnt->mnt_sb;
@@ -653,6 +655,9 @@ static int do_umount(struct vfsmount *mnt, int flags)
spin_lock(&vfsmount_lock);
event++;
+ if (!(flags & MNT_DETACH))
+ shrink_submounts(mnt, &umount_list);
+
retval = -EBUSY;
if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
if (!list_empty(&mnt->mnt_list))
@@ -1302,30 +1307,22 @@ resume:
* process a list of expirable mountpoints with the intent of discarding any
* submounts of a specific parent mountpoint
*/
-void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts)
+static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts)
{
LIST_HEAD(graveyard);
- LIST_HEAD(umounts);
- struct vfsmount *mnt;
+ struct vfsmount *m;
- down_write(&namespace_sem);
- spin_lock(&vfsmount_lock);
/* extract submounts of 'mountpoint' from the expiration list */
- while (select_submounts(mountpoint, &graveyard)) {
+ while (select_submounts(mnt, &graveyard)) {
while (!list_empty(&graveyard)) {
- mnt = list_first_entry(&graveyard, struct vfsmount,
+ m = list_first_entry(&graveyard, struct vfsmount,
mnt_expire);
touch_mnt_namespace(mnt->mnt_ns);
- umount_tree(mnt, 1, &umounts);
+ umount_tree(mnt, 1, umounts);
}
}
- spin_unlock(&vfsmount_lock);
- up_write(&namespace_sem);
- release_mounts(&umounts);
}
-EXPORT_SYMBOL_GPL(shrink_submounts);
-
/*
* Some copy_from_user() implementations do not return the exact number of
* bytes remaining to copy on a fault. But copy_mount_options() requires that.
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index dd4dfcd632ec..f9219024f31a 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -589,8 +589,6 @@ static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb);
struct rpc_clnt *rpc;
- shrink_submounts(vfsmnt, &nfs_automount_list);
-
if (!(flags & MNT_FORCE))
return;
/* -EIO all pending I/O */