[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>

Al Viro 7c4b93d8 1a390689

+6 -2
+4 -1
fs/namespace.c
··· 548 m = mnt->mnt_parent; 549 mnt->mnt_mountpoint = mnt->mnt_root; 550 mnt->mnt_parent = mnt; 551 spin_unlock(&vfsmount_lock); 552 dput(dentry); 553 mntput(m); ··· 573 __touch_mnt_namespace(p->mnt_ns); 574 p->mnt_ns = NULL; 575 list_del_init(&p->mnt_child); 576 - if (p->mnt_parent != p) 577 p->mnt_mountpoint->d_mounted--; 578 change_mnt_propagation(p, MS_PRIVATE); 579 } 580 }
··· 548 m = mnt->mnt_parent; 549 mnt->mnt_mountpoint = mnt->mnt_root; 550 mnt->mnt_parent = mnt; 551 + m->mnt_ghosts--; 552 spin_unlock(&vfsmount_lock); 553 dput(dentry); 554 mntput(m); ··· 572 __touch_mnt_namespace(p->mnt_ns); 573 p->mnt_ns = NULL; 574 list_del_init(&p->mnt_child); 575 + if (p->mnt_parent != p) { 576 + p->mnt_parent->mnt_ghosts++; 577 p->mnt_mountpoint->d_mounted--; 578 + } 579 change_mnt_propagation(p, MS_PRIVATE); 580 } 581 }
+1 -1
fs/pnode.c
··· 225 */ 226 static inline int do_refcount_check(struct vfsmount *mnt, int count) 227 { 228 - int mycount = atomic_read(&mnt->mnt_count); 229 return (mycount > count); 230 } 231
··· 225 */ 226 static inline int do_refcount_check(struct vfsmount *mnt, int count) 227 { 228 + int mycount = atomic_read(&mnt->mnt_count) - mnt->mnt_ghosts; 229 return (mycount > count); 230 } 231
+1
include/linux/mount.h
··· 61 atomic_t mnt_count; 62 int mnt_expiry_mark; /* true if marked for expiry */ 63 int mnt_pinned; 64 }; 65 66 static inline struct vfsmount *mntget(struct vfsmount *mnt)
··· 61 atomic_t mnt_count; 62 int mnt_expiry_mark; /* true if marked for expiry */ 63 int mnt_pinned; 64 + int mnt_ghosts; 65 }; 66 67 static inline struct vfsmount *mntget(struct vfsmount *mnt)