diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-03-28 18:23:01 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-03-28 18:23:01 -0400 |
| commit | af8be4e4b316df36a00c1e52a9970c253783b57e (patch) | |
| tree | 6d56665916e601ed6a933d6f85c22ee8512c6531 | |
| parent | d478376cb0dc9ab16a2b6e02fd8cd1174e724c64 (diff) | |
| parent | 6758f953d05378d907a164c67934cd86183d9c88 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
[PATCH] mnt_expire is protected by namespace_sem, no need for vfsmount_lock
[PATCH] do shrink_submounts() for all fs types
[PATCH] sanitize locking in mark_mounts_for_expiry() and shrink_submounts()
[PATCH] count ghost references to vfsmounts
[PATCH] reduce stack footprint in namespace.c
| -rw-r--r-- | fs/afs/internal.h | 1 | ||||
| -rw-r--r-- | fs/afs/mntpt.c | 8 | ||||
| -rw-r--r-- | fs/afs/super.c | 1 | ||||
| -rw-r--r-- | fs/cifs/cifs_dfs_ref.c | 1 | ||||
| -rw-r--r-- | fs/namespace.c | 200 | ||||
| -rw-r--r-- | fs/nfs/super.c | 2 | ||||
| -rw-r--r-- | fs/pnode.c | 2 | ||||
| -rw-r--r-- | include/linux/mount.h | 2 |
8 files changed, 71 insertions, 146 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 | ||
| 574 | extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *); | 574 | extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *); |
| 575 | extern void afs_mntpt_kill_timer(void); | 575 | extern void afs_mntpt_kill_timer(void); |
| 576 | extern 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 | */ | ||
| 290 | void 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 7953c96a2071..94f026ec990a 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -155,15 +155,15 @@ static void __touch_mnt_namespace(struct mnt_namespace *ns) | |||
| 155 | } | 155 | } |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) | 158 | static void detach_mnt(struct vfsmount *mnt, struct path *old_path) |
| 159 | { | 159 | { |
| 160 | old_nd->path.dentry = mnt->mnt_mountpoint; | 160 | old_path->dentry = mnt->mnt_mountpoint; |
| 161 | old_nd->path.mnt = mnt->mnt_parent; | 161 | old_path->mnt = mnt->mnt_parent; |
| 162 | mnt->mnt_parent = mnt; | 162 | mnt->mnt_parent = mnt; |
| 163 | mnt->mnt_mountpoint = mnt->mnt_root; | 163 | mnt->mnt_mountpoint = mnt->mnt_root; |
| 164 | list_del_init(&mnt->mnt_child); | 164 | list_del_init(&mnt->mnt_child); |
| 165 | list_del_init(&mnt->mnt_hash); | 165 | list_del_init(&mnt->mnt_hash); |
| 166 | old_nd->path.dentry->d_mounted--; | 166 | old_path->dentry->d_mounted--; |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, | 169 | void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, |
| @@ -174,12 +174,12 @@ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, | |||
| 174 | dentry->d_mounted++; | 174 | dentry->d_mounted++; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd) | 177 | static void attach_mnt(struct vfsmount *mnt, struct path *path) |
| 178 | { | 178 | { |
| 179 | mnt_set_mountpoint(nd->path.mnt, nd->path.dentry, mnt); | 179 | mnt_set_mountpoint(path->mnt, path->dentry, mnt); |
| 180 | list_add_tail(&mnt->mnt_hash, mount_hashtable + | 180 | list_add_tail(&mnt->mnt_hash, mount_hashtable + |
| 181 | hash(nd->path.mnt, nd->path.dentry)); | 181 | hash(path->mnt, path->dentry)); |
| 182 | list_add_tail(&mnt->mnt_child, &nd->path.mnt->mnt_mounts); | 182 | list_add_tail(&mnt->mnt_child, &path->mnt->mnt_mounts); |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | /* | 185 | /* |
| @@ -262,10 +262,8 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, | |||
| 262 | /* stick the duplicate mount on the same expiry list | 262 | /* stick the duplicate mount on the same expiry list |
| 263 | * as the original if that was on one */ | 263 | * as the original if that was on one */ |
| 264 | if (flag & CL_EXPIRE) { | 264 | if (flag & CL_EXPIRE) { |
| 265 | spin_lock(&vfsmount_lock); | ||
| 266 | if (!list_empty(&old->mnt_expire)) | 265 | if (!list_empty(&old->mnt_expire)) |
| 267 | list_add(&mnt->mnt_expire, &old->mnt_expire); | 266 | list_add(&mnt->mnt_expire, &old->mnt_expire); |
| 268 | spin_unlock(&vfsmount_lock); | ||
| 269 | } | 267 | } |
| 270 | } | 268 | } |
| 271 | return mnt; | 269 | return mnt; |
| @@ -548,6 +546,7 @@ void release_mounts(struct list_head *head) | |||
| 548 | m = mnt->mnt_parent; | 546 | m = mnt->mnt_parent; |
| 549 | mnt->mnt_mountpoint = mnt->mnt_root; | 547 | mnt->mnt_mountpoint = mnt->mnt_root; |
| 550 | mnt->mnt_parent = mnt; | 548 | mnt->mnt_parent = mnt; |
| 549 | m->mnt_ghosts--; | ||
| 551 | spin_unlock(&vfsmount_lock); | 550 | spin_unlock(&vfsmount_lock); |
| 552 | dput(dentry); | 551 | dput(dentry); |
| 553 | mntput(m); | 552 | mntput(m); |
| @@ -572,12 +571,16 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) | |||
| 572 | __touch_mnt_namespace(p->mnt_ns); | 571 | __touch_mnt_namespace(p->mnt_ns); |
| 573 | p->mnt_ns = NULL; | 572 | p->mnt_ns = NULL; |
| 574 | list_del_init(&p->mnt_child); | 573 | list_del_init(&p->mnt_child); |
| 575 | if (p->mnt_parent != p) | 574 | if (p->mnt_parent != p) { |
| 575 | p->mnt_parent->mnt_ghosts++; | ||
| 576 | p->mnt_mountpoint->d_mounted--; | 576 | p->mnt_mountpoint->d_mounted--; |
| 577 | } | ||
| 577 | change_mnt_propagation(p, MS_PRIVATE); | 578 | change_mnt_propagation(p, MS_PRIVATE); |
| 578 | } | 579 | } |
| 579 | } | 580 | } |
| 580 | 581 | ||
| 582 | static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts); | ||
| 583 | |||
| 581 | static int do_umount(struct vfsmount *mnt, int flags) | 584 | static int do_umount(struct vfsmount *mnt, int flags) |
| 582 | { | 585 | { |
| 583 | struct super_block *sb = mnt->mnt_sb; | 586 | struct super_block *sb = mnt->mnt_sb; |
| @@ -650,6 +653,9 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
| 650 | spin_lock(&vfsmount_lock); | 653 | spin_lock(&vfsmount_lock); |
| 651 | event++; | 654 | event++; |
| 652 | 655 | ||
| 656 | if (!(flags & MNT_DETACH)) | ||
| 657 | shrink_submounts(mnt, &umount_list); | ||
| 658 | |||
| 653 | retval = -EBUSY; | 659 | retval = -EBUSY; |
| 654 | if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { | 660 | if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { |
| 655 | if (!list_empty(&mnt->mnt_list)) | 661 | if (!list_empty(&mnt->mnt_list)) |
| @@ -744,7 +750,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, | |||
| 744 | int flag) | 750 | int flag) |
| 745 | { | 751 | { |
| 746 | struct vfsmount *res, *p, *q, *r, *s; | 752 | struct vfsmount *res, *p, *q, *r, *s; |
| 747 | struct nameidata nd; | 753 | struct path path; |
| 748 | 754 | ||
| 749 | if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) | 755 | if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) |
| 750 | return NULL; | 756 | return NULL; |
| @@ -769,14 +775,14 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, | |||
| 769 | q = q->mnt_parent; | 775 | q = q->mnt_parent; |
| 770 | } | 776 | } |
| 771 | p = s; | 777 | p = s; |
| 772 | nd.path.mnt = q; | 778 | path.mnt = q; |
| 773 | nd.path.dentry = p->mnt_mountpoint; | 779 | path.dentry = p->mnt_mountpoint; |
| 774 | q = clone_mnt(p, p->mnt_root, flag); | 780 | q = clone_mnt(p, p->mnt_root, flag); |
| 775 | if (!q) | 781 | if (!q) |
| 776 | goto Enomem; | 782 | goto Enomem; |
| 777 | spin_lock(&vfsmount_lock); | 783 | spin_lock(&vfsmount_lock); |
| 778 | list_add_tail(&q->mnt_list, &res->mnt_list); | 784 | list_add_tail(&q->mnt_list, &res->mnt_list); |
