diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2008-03-21 23:59:49 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-03-27 20:47:46 -0400 |
commit | 7c4b93d8269b9d35971a8239426b1f6ddc3d5ef7 (patch) | |
tree | a3309f9237f9d67af000e484bef9c19a7951750a | |
parent | 1a39068954e33f4bf3e09375a8112dcc801c4688 (diff) |
[PATCH] count ghost references to vfsmounts
make propagate_mount_busy() exclude references from the vfsmounts
that had been isolated by umount_tree() and are just waiting for
release_mounts() to dispose of their ->mnt_parent/->mnt_mountpoint.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/namespace.c | 5 | ||||
-rw-r--r-- | fs/pnode.c | 2 | ||||
-rw-r--r-- | include/linux/mount.h | 1 |
3 files changed, 6 insertions, 2 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 6324dfc80dc6..c175218ebae1 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -548,6 +548,7 @@ void release_mounts(struct list_head *head) | |||
548 | m = mnt->mnt_parent; | 548 | m = mnt->mnt_parent; |
549 | mnt->mnt_mountpoint = mnt->mnt_root; | 549 | mnt->mnt_mountpoint = mnt->mnt_root; |
550 | mnt->mnt_parent = mnt; | 550 | mnt->mnt_parent = mnt; |
551 | m->mnt_ghosts--; | ||
551 | spin_unlock(&vfsmount_lock); | 552 | spin_unlock(&vfsmount_lock); |
552 | dput(dentry); | 553 | dput(dentry); |
553 | mntput(m); | 554 | mntput(m); |
@@ -572,8 +573,10 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) | |||
572 | __touch_mnt_namespace(p->mnt_ns); | 573 | __touch_mnt_namespace(p->mnt_ns); |
573 | p->mnt_ns = NULL; | 574 | p->mnt_ns = NULL; |
574 | list_del_init(&p->mnt_child); | 575 | list_del_init(&p->mnt_child); |
575 | if (p->mnt_parent != p) | 576 | if (p->mnt_parent != p) { |
577 | p->mnt_parent->mnt_ghosts++; | ||
576 | p->mnt_mountpoint->d_mounted--; | 578 | p->mnt_mountpoint->d_mounted--; |
579 | } | ||
577 | change_mnt_propagation(p, MS_PRIVATE); | 580 | change_mnt_propagation(p, MS_PRIVATE); |
578 | } | 581 | } |
579 | } | 582 | } |
diff --git a/fs/pnode.c b/fs/pnode.c index 05ba692bc540..1d8f5447f3f7 100644 --- a/fs/pnode.c +++ b/fs/pnode.c | |||
@@ -225,7 +225,7 @@ out: | |||
225 | */ | 225 | */ |
226 | static inline int do_refcount_check(struct vfsmount *mnt, int count) | 226 | static inline int do_refcount_check(struct vfsmount *mnt, int count) |
227 | { | 227 | { |
228 | int mycount = atomic_read(&mnt->mnt_count); | 228 | int mycount = atomic_read(&mnt->mnt_count) - mnt->mnt_ghosts; |
229 | return (mycount > count); | 229 | return (mycount > count); |
230 | } | 230 | } |
231 | 231 | ||
diff --git a/include/linux/mount.h b/include/linux/mount.h index 6d3047d8c91c..dac5e67ff3ee 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h | |||
@@ -61,6 +61,7 @@ struct vfsmount { | |||
61 | atomic_t mnt_count; | 61 | atomic_t mnt_count; |
62 | int mnt_expiry_mark; /* true if marked for expiry */ | 62 | int mnt_expiry_mark; /* true if marked for expiry */ |
63 | int mnt_pinned; | 63 | int mnt_pinned; |
64 | int mnt_ghosts; | ||
64 | }; | 65 | }; |
65 | 66 | ||
66 | static inline struct vfsmount *mntget(struct vfsmount *mnt) | 67 | static inline struct vfsmount *mntget(struct vfsmount *mnt) |