aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2008-03-22 00:46:23 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2008-03-27 20:47:58 -0400
commitc35038becad0adb0e25261fff66d85b1a6ddd0c2 (patch)
tree1d375d74ef5b4c3641768697b2ff8f4992916dc5
parentbcc5c7d2b692e5319db00b0dd020ce98723103b1 (diff)
[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>
-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
-rw-r--r--include/linux/mount.h1
7 files changed, 10 insertions, 27 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;
573 573
574extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *); 574extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *);
575extern void afs_mntpt_kill_timer(void); 575extern void afs_mntpt_kill_timer(void);
576extern void afs_umount_begin(struct vfsmount *, int);
577 576
578/* 577/*
579 * proc.c 578 * 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)
283 cancel_delayed_work(&afs_mntpt_expiry_timer); 283 cancel_delayed_work(&afs_mntpt_expiry_timer);
284 flush_scheduled_work(); 284 flush_scheduled_work();
285} 285}
286
287/*
288 * begin unmount by attempting to remove all automounted mountpoints we added
289 */
290void afs_umount_begin(struct vfsmount *vfsmnt, int flags)
291{
292 shrink_submounts(vfsmnt, &afs_vfsmounts);
293}
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 = {
50 .write_inode = afs_write_inode, 50 .write_inode = afs_write_inode,
51 .destroy_inode = afs_destroy_inode, 51 .destroy_inode = afs_destroy_inode,
52 .clear_inode = afs_clear_inode, 52 .clear_inode = afs_clear_inode,
53 .umount_begin = afs_umount_begin,
54 .put_super = afs_put_super, 53 .put_super = afs_put_super,
55 .show_options = generic_show_options, 54 .show_options = generic_show_options,
56}; 55};
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)
33{ 33{
34 mark_mounts_for_expiry(&cifs_dfs_automount_list); 34 mark_mounts_for_expiry(&cifs_dfs_automount_list);
35 mark_mounts_for_expiry(&cifs_dfs_automount_list); 35 mark_mounts_for_expiry(&cifs_dfs_automount_list);
36 shrink_submounts(vfsmnt, &cifs_dfs_automount_list);
37} 36}
38 37
39/** 38/**
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)
581 } 581 }
582} 582}
583 583
584static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts);
585
584static int do_umount(struct vfsmount *mnt, int flags) 586static int do_umount(struct vfsmount *mnt, int flags)
585{ 587{
586 struct super_block *sb = mnt->mnt_sb; 588 struct super_block *sb = mnt->mnt_sb;
@@ -653,6 +655,9 @@ static int do_umount(struct vfsmount *mnt, int flags)
653 spin_lock(&vfsmount_lock); 655 spin_lock(&vfsmount_lock);
654 event++; 656 event++;
655 657
658 if (!(flags & MNT_DETACH))
659 shrink_submounts(mnt, &umount_list);
660
656 retval = -EBUSY; 661 retval = -EBUSY;
657 if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { 662 if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
658 if (!list_empty(&mnt->mnt_list)) 663 if (!list_empty(&mnt->mnt_list))
@@ -1302,30 +1307,22 @@ resume:
1302 * process a list of expirable mountpoints with the intent of discarding any 1307 * process a list of expirable mountpoints with the intent of discarding any
1303 * submounts of a specific parent mountpoint 1308 * submounts of a specific parent mountpoint
1304 */ 1309 */
1305void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts) 1310static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts)
1306{ 1311{
1307 LIST_HEAD(graveyard); 1312 LIST_HEAD(graveyard);
1308 LIST_HEAD(umounts); 1313 struct vfsmount *m;
1309 struct vfsmount *mnt;
1310 1314
1311 down_write(&namespace_sem);
1312 spin_lock(&vfsmount_lock);
1313 /* extract submounts of 'mountpoint' from the expiration list */ 1315 /* extract submounts of 'mountpoint' from the expiration list */
1314 while (select_submounts(mountpoint, &graveyard)) { 1316 while (select_submounts(mnt, &graveyard)) {
1315 while (!list_empty(&graveyard)) { 1317 while (!list_empty(&graveyard)) {
1316 mnt = list_first_entry(&graveyard, struct vfsmount, 1318 m = list_first_entry(&graveyard, struct vfsmount,
1317 mnt_expire); 1319 mnt_expire);
1318 touch_mnt_namespace(mnt->mnt_ns); 1320 touch_mnt_namespace(mnt->mnt_ns);
1319 umount_tree(mnt, 1, &umounts); 1321 umount_tree(mnt, 1, umounts);
1320 } 1322 }
1321 } 1323 }
1322 spin_unlock(&vfsmount_lock);
1323 up_write(&namespace_sem);
1324 release_mounts(&umounts);
1325} 1324}
1326 1325
1327EXPORT_SYMBOL_GPL(shrink_submounts);
1328
1329/* 1326/*
1330 * Some copy_from_user() implementations do not return the exact number of 1327 * Some copy_from_user() implementations do not return the exact number of
1331 * bytes remaining to copy on a fault. But copy_mount_options() requires that. 1328 * 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)
589 struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb); 589 struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb);
590 struct rpc_clnt *rpc; 590 struct rpc_clnt *rpc;
591 591
592 shrink_submounts(vfsmnt, &nfs_automount_list);
593
594 if (!(flags & MNT_FORCE)) 592 if (!(flags & MNT_FORCE))
595 return; 593 return;
596 /* -EIO all pending I/O */ 594 /* -EIO all pending I/O */
diff --git a/include/linux/mount.h b/include/linux/mount.h
index dac5e67ff3ee..5ee2df217cdf 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -99,7 +99,6 @@ extern int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
99 int mnt_flags, struct list_head *fslist); 99 int mnt_flags, struct list_head *fslist);
100 100
101extern void mark_mounts_for_expiry(struct list_head *mounts); 101extern void mark_mounts_for_expiry(struct list_head *mounts);
102extern void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts);
103 102
104extern spinlock_t vfsmount_lock; 103extern spinlock_t vfsmount_lock;
105extern dev_t name_to_dev_t(char *name); 104extern dev_t name_to_dev_t(char *name);