[PATCH] count ghost references to vfsmounts
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 22 Mar 2008 03:59:49 +0000 (23:59 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 28 Mar 2008 00:47:46 +0000 (20:47 -0400)
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>
fs/namespace.c
fs/pnode.c
include/linux/mount.h

index 6324dfc80dc6d7f8331c1663520ba093818f2301..c175218ebae1690854760a407784a3ebb592c62c 100644 (file)
@@ -548,6 +548,7 @@ void release_mounts(struct list_head *head)
                        m = mnt->mnt_parent;
                        mnt->mnt_mountpoint = mnt->mnt_root;
                        mnt->mnt_parent = mnt;
+                       m->mnt_ghosts--;
                        spin_unlock(&vfsmount_lock);
                        dput(dentry);
                        mntput(m);
@@ -572,8 +573,10 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
                __touch_mnt_namespace(p->mnt_ns);
                p->mnt_ns = NULL;
                list_del_init(&p->mnt_child);
-               if (p->mnt_parent != p)
+               if (p->mnt_parent != p) {
+                       p->mnt_parent->mnt_ghosts++;
                        p->mnt_mountpoint->d_mounted--;
+               }
                change_mnt_propagation(p, MS_PRIVATE);
        }
 }
index 05ba692bc540ade3b63c5f5af72e1987556bd9fe..1d8f5447f3f7c533bc848883694bf7656428a64b 100644 (file)
@@ -225,7 +225,7 @@ out:
  */
 static inline int do_refcount_check(struct vfsmount *mnt, int count)
 {
-       int mycount = atomic_read(&mnt->mnt_count);
+       int mycount = atomic_read(&mnt->mnt_count) - mnt->mnt_ghosts;
        return (mycount > count);
 }
 
index 6d3047d8c91c877b9243a5093557ef77c5e61774..dac5e67ff3ee2b9dbfbebe9fb52420c324fc6535 100644 (file)
@@ -61,6 +61,7 @@ struct vfsmount {
        atomic_t mnt_count;
        int mnt_expiry_mark;            /* true if marked for expiry */
        int mnt_pinned;
+       int mnt_ghosts;
 };
 
 static inline struct vfsmount *mntget(struct vfsmount *mnt)