Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 4 Oct 2012 12:11:07 +0300
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        Norbert Aschendorff <norbert.aschendorff@yahoo.de>
Cc:        freebsd-stable@freebsd.org
Subject:   Re: panic "Sleeping thread owns a non-sleepable lock" via cv_timedwait_signal, was "rsync over NFS"
Message-ID:  <20121004091106.GF35915@deviant.kiev.zoral.com.ua>
In-Reply-To: <506D474D.6090107@yahoo.de>
References:  <506BFECE.3020006@yahoo.de> <37099006.1631279.1349270651574.JavaMail.root@erie.cs.uoguelph.ca> <20121003155452.GY35915@deviant.kiev.zoral.com.ua> <506C7557.1000503@yahoo.de> <20121003173931.GZ35915@deviant.kiev.zoral.com.ua> <506D2FA9.2050605@yahoo.de> <506D35D8.8090702@yahoo.de> <20121004080902.GD35915@deviant.kiev.zoral.com.ua> <506D474D.6090107@yahoo.de>

next in thread | previous in thread | raw e-mail | index | archive | help

--Uaw16JuuybUwHkzF
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Thu, Oct 04, 2012 at 10:22:37AM +0200, Norbert Aschendorff wrote:
> Hehe, sure, if you assist me :)
> I'm not very experienced with SVN, I'm actually a git user and I think
> it's also better if I do /not/ express my opinion on SVN here ;)
> The only actions I'm currently able to do in SVN are checkout, update,
> commit and view log and status -- so any help is appreciated :P

I merged the changes for you, try the patch below.

Index: .
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- .	(revision 241191)
+++ .	(working copy)

Property changes on: .
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys:r240283-240285
Index: fs
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- fs	(revision 241191)
+++ fs	(working copy)

Property changes on: fs
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/sys/fs:r240285
Index: fs/nullfs/null.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- fs/nullfs/null.h	(revision 241191)
+++ fs/nullfs/null.h	(working copy)
@@ -56,6 +56,7 @@
 int nullfs_init(struct vfsconf *vfsp);
 int nullfs_uninit(struct vfsconf *vfsp);
 int null_nodeget(struct mount *mp, struct vnode *target, struct vnode **vp=
p);
+struct vnode *null_hashget(struct mount *mp, struct vnode *lowervp);
 void null_hashrem(struct null_node *xp);
 int null_bypass(struct vop_generic_args *ap);
=20
Index: fs/nullfs/null_subr.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- fs/nullfs/null_subr.c	(revision 241191)
+++ fs/nullfs/null_subr.c	(working copy)
@@ -67,7 +67,6 @@
 static MALLOC_DEFINE(M_NULLFSHASH, "nullfs_hash", "NULLFS hash table");
 MALLOC_DEFINE(M_NULLFSNODE, "nullfs_node", "NULLFS vnode private part");
=20
-static struct vnode * null_hashget(struct mount *, struct vnode *);
 static struct vnode * null_hashins(struct mount *, struct null_node *);
=20
 /*
@@ -98,7 +97,7 @@
  * Return a VREF'ed alias for lower vnode if already exists, else 0.
  * Lower vnode should be locked on entry and will be left locked on exit.
  */
-static struct vnode *
+struct vnode *
 null_hashget(mp, lowervp)
 	struct mount *mp;
 	struct vnode *lowervp;
@@ -209,14 +208,10 @@
 	struct vnode *vp;
 	int error;
=20
-	/*
-	 * The insmntque1() call below requires the exclusive lock on
-	 * the nullfs vnode.
-	 */
-	ASSERT_VOP_ELOCKED(lowervp, "lowervp");
-	KASSERT(lowervp->v_usecount >=3D 1, ("Unreferenced vnode %p\n", lowervp));
+	ASSERT_VOP_LOCKED(lowervp, "lowervp");
+	KASSERT(lowervp->v_usecount >=3D 1, ("Unreferenced vnode %p", lowervp));
=20
-	/* Lookup the hash firstly */
+	/* Lookup the hash firstly. */
 	*vpp =3D null_hashget(mp, lowervp);
 	if (*vpp !=3D NULL) {
 		vrele(lowervp);
@@ -224,6 +219,19 @@
 	}
=20
 	/*
+	 * The insmntque1() call below requires the exclusive lock on
+	 * the nullfs vnode.  Upgrade the lock now if hash failed to
+	 * provide ready to use vnode.
+	 */
+	if (VOP_ISLOCKED(lowervp) !=3D LK_EXCLUSIVE) {
+		vn_lock(lowervp, LK_UPGRADE | LK_RETRY);
+		if ((lowervp->v_iflag & VI_DOOMED) !=3D 0) {
+			vput(lowervp);
+			return (ENOENT);
+		}
+	}
+
+	/*
 	 * We do not serialize vnode creation, instead we will check for
 	 * duplicates later, when adding new vnode to hash.
 	 * Note that duplicate can only appear in hash if the lowervp is
@@ -233,8 +241,7 @@
 	 * might cause a bogus v_data pointer to get dereferenced
 	 * elsewhere if MALLOC should block.
 	 */
-	xp =3D malloc(sizeof(struct null_node),
-	    M_NULLFSNODE, M_WAITOK);
+	xp =3D malloc(sizeof(struct null_node), M_NULLFSNODE, M_WAITOK);
=20
 	error =3D getnewvnode("null", mp, &null_vnodeops, &vp);
 	if (error) {
Index: fs/nullfs/null_vfsops.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- fs/nullfs/null_vfsops.c	(revision 241191)
+++ fs/nullfs/null_vfsops.c	(working copy)
@@ -65,6 +65,7 @@
 static vfs_unmount_t	nullfs_unmount;
 static vfs_vget_t	nullfs_vget;
 static vfs_extattrctl_t	nullfs_extattrctl;
+static vfs_reclaim_lowervp_t nullfs_reclaim_lowervp;
=20
 /*
  * Mount null layer
@@ -121,8 +122,10 @@
 	 */
 	NDINIT(ndp, LOOKUP, FOLLOW|LOCKLEAF, UIO_SYSSPACE, target, curthread);
 	error =3D namei(ndp);
+
 	/*
 	 * Re-lock vnode.
+	 * XXXKIB This is deadlock-prone as well.
 	 */
 	if (isvnunlocked)
 		vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY);
@@ -146,7 +149,7 @@
 	}
=20
 	xmp =3D (struct null_mount *) malloc(sizeof(struct null_mount),
-				M_NULLFSMNT, M_WAITOK);	/* XXX */
+	    M_NULLFSMNT, M_WAITOK);
=20
 	/*
 	 * Save reference to underlying FS
@@ -186,10 +189,15 @@
 	}
 	MNT_ILOCK(mp);
 	mp->mnt_kern_flag |=3D lowerrootvp->v_mount->mnt_kern_flag &
-	    (MNTK_MPSAFE | MNTK_SHARED_WRITES);
+	    (MNTK_MPSAFE | MNTK_SHARED_WRITES | MNTK_LOOKUP_SHARED |
+	    MNTK_EXTENDED_SHARED);
+	mp->mnt_kern_flag |=3D MNTK_LOOKUP_EXCL_DOTDOT;
 	MNT_IUNLOCK(mp);
 	mp->mnt_data =3D  xmp;
 	vfs_getnewfsid(mp);
+	MNT_ILOCK(xmp->nullm_vfs);
+	TAILQ_INSERT_TAIL(&xmp->nullm_vfs->mnt_uppers, mp, mnt_upper_link);
+	MNT_IUNLOCK(xmp->nullm_vfs);
=20
 	vfs_mountedfrom(mp, target);
=20
@@ -206,14 +214,16 @@
 	struct mount *mp;
 	int mntflags;
 {
-	void *mntdata;
-	int error;
-	int flags =3D 0;
+	struct null_mount *mntdata;
+	struct mount *ump;
+	int error, flags;
=20
 	NULLFSDEBUG("nullfs_unmount: mp =3D %p\n", (void *)mp);
=20
 	if (mntflags & MNT_FORCE)
-		flags |=3D FORCECLOSE;
+		flags =3D FORCECLOSE;
+	else
+		flags =3D 0;
=20
 	/* There is 1 extra root vnode reference (nullm_rootvp). */
 	error =3D vflush(mp, 1, flags, curthread);
@@ -224,9 +234,17 @@
 	 * Finally, throw away the null_mount structure
 	 */
 	mntdata =3D mp->mnt_data;
-	mp->mnt_data =3D 0;
+	ump =3D mntdata->nullm_vfs;
+	MNT_ILOCK(ump);
+	while ((ump->mnt_kern_flag & MNTK_VGONE_UPPER) !=3D 0) {
+		ump->mnt_kern_flag |=3D MNTK_VGONE_WAITER;
+		msleep(&ump->mnt_uppers, &ump->mnt_mtx, 0, "vgnupw", 0);
+	}
+	TAILQ_REMOVE(&ump->mnt_uppers, mp, mnt_upper_link);
+	MNT_IUNLOCK(ump);
+	mp->mnt_data =3D NULL;
 	free(mntdata, M_NULLFSMNT);
-	return 0;
+	return (0);
 }
=20
 static int
@@ -316,13 +334,10 @@
=20
 	KASSERT((flags & LK_TYPE_MASK) !=3D 0,
 	    ("nullfs_vget: no lock requested"));
-	flags &=3D ~LK_TYPE_MASK;
-	flags |=3D LK_EXCLUSIVE;
=20
 	error =3D VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, flags, vpp);
-	if (error)
+	if (error !=3D 0)
 		return (error);
-
 	return (null_nodeget(mp, *vpp, vpp));
 }
=20
@@ -334,11 +349,11 @@
 	struct vnode **vpp;
 {
 	int error;
-	error =3D VFS_FHTOVP(MOUNTTONULLMOUNT(mp)->nullm_vfs, fidp, LK_EXCLUSIVE,
+
+	error =3D VFS_FHTOVP(MOUNTTONULLMOUNT(mp)->nullm_vfs, fidp, flags,
 	    vpp);
-	if (error)
+	if (error !=3D 0)
 		return (error);
-
 	return (null_nodeget(mp, *vpp, vpp));
 }
=20
@@ -350,11 +365,23 @@
 	int namespace;
 	const char *attrname;
 {
-	return VFS_EXTATTRCTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd, filename_vp,
-	    namespace, attrname);
+
+	return (VFS_EXTATTRCTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd,
+	    filename_vp, namespace, attrname));
 }
=20
+static void
+nullfs_reclaim_lowervp(struct mount *mp, struct vnode *lowervp)
+{
+	struct vnode *vp;
=20
+	vp =3D null_hashget(mp, lowervp);
+	if (vp =3D=3D NULL)
+		return;
+	vgone(vp);
+	vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY);
+}
+
 static struct vfsops null_vfsops =3D {
 	.vfs_extattrctl =3D	nullfs_extattrctl,
 	.vfs_fhtovp =3D		nullfs_fhtovp,
@@ -367,6 +394,7 @@
 	.vfs_uninit =3D		nullfs_uninit,
 	.vfs_unmount =3D		nullfs_unmount,
 	.vfs_vget =3D		nullfs_vget,
+	.vfs_reclaim_lowervp =3D	nullfs_reclaim_lowervp,
 };
=20
 VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK | VFCF_JAIL);
Index: fs/nullfs/null_vnops.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- fs/nullfs/null_vnops.c	(revision 241191)
+++ fs/nullfs/null_vnops.c	(working copy)
@@ -665,34 +665,19 @@
 }
=20
 /*
- * There is no way to tell that someone issued remove/rmdir operation
- * on the underlying filesystem. For now we just have to release lowervp
- * as soon as possible.
- *
- * Note, we can't release any resources nor remove vnode from hash before=
=20
- * appropriate VXLOCK stuff is done because other process can find this
- * vnode in hash during inactivation and may be sitting in vget() and wait=
ing
- * for null_inactive to unlock vnode. Thus we will do all those in VOP_REC=
LAIM.
+ * XXXKIB
  */
 static int
-null_inactive(struct vop_inactive_args *ap)
+null_inactive(struct vop_inactive_args *ap __unused)
 {
-	struct vnode *vp =3D ap->a_vp;
 	struct thread *td =3D ap->a_td;
=20
-	vp->v_object =3D NULL;
-
-	/*
-	 * If this is the last reference, then free up the vnode
-	 * so as not to tie up the lower vnodes.
-	 */
-	vrecycle(vp, td);
-
 	return (0);
 }
=20
 /*
- * Now, the VXLOCK is in force and we're free to destroy the null vnode.
+ * Now, the nullfs vnode and, due to the sharing lock, the lower
+ * vnode, are exclusively locked, and we shall destroy the null vnode.
  */
 static int
 null_reclaim(struct vop_reclaim_args *ap)
Index: kern/vfs_lookup.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- kern/vfs_lookup.c	(revision 241191)
+++ kern/vfs_lookup.c	(working copy)
@@ -396,11 +396,13 @@
 }
=20
 static int
-compute_cn_lkflags(struct mount *mp, int lkflags)
+compute_cn_lkflags(struct mount *mp, int lkflags, int cnflags)
 {
=20
-	if (mp =3D=3D NULL ||=20
-	    ((lkflags & LK_SHARED) && !(mp->mnt_kern_flag & MNTK_LOOKUP_SHARED)))=
 {
+	if (mp =3D=3D NULL || ((lkflags & LK_SHARED) &&
+	    (!(mp->mnt_kern_flag & MNTK_LOOKUP_SHARED) ||
+	    ((cnflags & ISDOTDOT) &&
+	    (mp->mnt_kern_flag & MNTK_LOOKUP_EXCL_DOTDOT))))) {
 		lkflags &=3D ~LK_SHARED;
 		lkflags |=3D LK_EXCLUSIVE;
 	}
@@ -529,7 +531,8 @@
 	dp =3D ndp->ni_startdir;
 	ndp->ni_startdir =3D NULLVP;
 	vn_lock(dp,
-	    compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags | LK_RETRY));
+	    compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags | LK_RETRY,
+	    cnp->cn_flags));
=20
 dirloop:
 	/*
@@ -686,7 +689,7 @@
 			VFS_UNLOCK_GIANT(tvfslocked);
 			vn_lock(dp,
 			    compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags |
-			    LK_RETRY));
+			    LK_RETRY, ISDOTDOT));
 		}
 	}
=20
@@ -724,7 +727,8 @@
 	vprint("lookup in", dp);
 #endif
 	lkflags_save =3D cnp->cn_lkflags;
-	cnp->cn_lkflags =3D compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags);
+	cnp->cn_lkflags =3D compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags,
+	    cnp->cn_flags);
 	if ((error =3D VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) !=3D 0) {
 		cnp->cn_lkflags =3D lkflags_save;
 		KASSERT(ndp->ni_vp =3D=3D NULL, ("leaf should be empty"));
@@ -743,7 +747,7 @@
 			VFS_UNLOCK_GIANT(tvfslocked);
 			vn_lock(dp,
 			    compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags |
-			    LK_RETRY));
+			    LK_RETRY, cnp->cn_flags));
 			goto unionlookup;
 		}
=20
@@ -815,8 +819,8 @@
 		dvfslocked =3D 0;
 		vref(vp_crossmp);
 		ndp->ni_dvp =3D vp_crossmp;
-		error =3D VFS_ROOT(mp, compute_cn_lkflags(mp, cnp->cn_lkflags),
-		    &tdp);
+		error =3D VFS_ROOT(mp, compute_cn_lkflags(mp, cnp->cn_lkflags,
+		    cnp->cn_flags), &tdp);
 		vfs_unbusy(mp);
 		if (vn_lock(vp_crossmp, LK_SHARED | LK_NOWAIT))
 			panic("vp_crossmp exclusively locked or reclaimed");
Index: kern/vfs_mount.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- kern/vfs_mount.c	(revision 241191)
+++ kern/vfs_mount.c	(working copy)
@@ -479,6 +479,7 @@
 	mac_mount_create(cred, mp);
 #endif
 	arc4rand(&mp->mnt_hashseed, sizeof mp->mnt_hashseed, 0);
+	TAILQ_INIT(&mp->mnt_uppers);
 	return (mp);
 }
=20
@@ -512,6 +513,7 @@
 			vprint("", vp);
 		panic("unmount: dangling vnode");
 	}
+	KASSERT(TAILQ_EMPTY(&mp->mnt_uppers), ("mnt_uppers"));
 	if (mp->mnt_nvnodelistsize !=3D 0)
 		panic("vfs_mount_destroy: nonzero nvnodelistsize");
 	if (mp->mnt_activevnodelistsize !=3D 0)
@@ -1260,7 +1262,8 @@
 	}
=20
 	MNT_ILOCK(mp);
-	if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
+	if ((mp->mnt_kern_flag & MNTK_UNMOUNT) !=3D 0 ||
+	    !TAILQ_EMPTY(&mp->mnt_uppers)) {
 		MNT_IUNLOCK(mp);
 		if (coveredvp)
 			VOP_UNLOCK(coveredvp, 0);
Index: kern/vfs_subr.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- kern/vfs_subr.c	(revision 241191)
+++ kern/vfs_subr.c	(working copy)
@@ -2689,7 +2689,59 @@
 	VI_UNLOCK(vp);
 }
=20
+static void
+vgonel_reclaim_lowervp_vfs(struct mount *mp __unused,
+    struct vnode *lowervp __unused)
+{
+}
+
 /*
+ * Notify upper mounts about reclaimed vnode.
+ */
+static void
+vgonel_reclaim_lowervp(struct vnode *vp)
+{
+	static struct vfsops vgonel_vfsops =3D {
+		.vfs_reclaim_lowervp =3D vgonel_reclaim_lowervp_vfs
+	};
+	struct mount *mp, *ump, *mmp;
+
+	mp =3D vp->v_mount;
+	if (mp =3D=3D NULL)
+		return;
+
+	MNT_ILOCK(mp);
+	if (TAILQ_EMPTY(&mp->mnt_uppers))
+		goto unlock;
+	MNT_IUNLOCK(mp);
+	mmp =3D malloc(sizeof(struct mount), M_TEMP, M_WAITOK | M_ZERO);
+	mmp->mnt_op =3D &vgonel_vfsops;
+	mmp->mnt_kern_flag |=3D MNTK_MARKER;
+	MNT_ILOCK(mp);
+	mp->mnt_kern_flag |=3D MNTK_VGONE_UPPER;
+	for (ump =3D TAILQ_FIRST(&mp->mnt_uppers); ump !=3D NULL;) {
+		if ((ump->mnt_kern_flag & MNTK_MARKER) !=3D 0) {
+			ump =3D TAILQ_NEXT(ump, mnt_upper_link);
+			continue;
+		}
+		TAILQ_INSERT_AFTER(&mp->mnt_uppers, ump, mmp, mnt_upper_link);
+		MNT_IUNLOCK(mp);
+		VFS_RECLAIM_LOWERVP(ump, vp);
+		MNT_ILOCK(mp);
+		ump =3D TAILQ_NEXT(mmp, mnt_upper_link);
+		TAILQ_REMOVE(&mp->mnt_uppers, mmp, mnt_upper_link);
+	}
+	free(mmp, M_TEMP);
+	mp->mnt_kern_flag &=3D ~MNTK_VGONE_UPPER;
+	if ((mp->mnt_kern_flag & MNTK_VGONE_WAITER) !=3D 0) {
+		mp->mnt_kern_flag &=3D ~MNTK_VGONE_WAITER;
+		wakeup(&mp->mnt_uppers);
+	}
+unlock:
+	MNT_IUNLOCK(mp);
+}
+
+/*
  * vgone, with the vp interlock held.
  */
 void
@@ -2713,6 +2765,7 @@
 	if (vp->v_iflag & VI_DOOMED)
 		return;
 	vp->v_iflag |=3D VI_DOOMED;
+
 	/*
 	 * Check to see if the vnode is in use.  If so, we have to call
 	 * VOP_CLOSE() and VOP_INACTIVE().
@@ -2720,6 +2773,8 @@
 	active =3D vp->v_usecount;
 	oweinact =3D (vp->v_iflag & VI_OWEINACT);
 	VI_UNLOCK(vp);
+	vgonel_reclaim_lowervp(vp);
+
 	/*
 	 * Clean out any buffers associated with the vnode.
 	 * If the flush fails, just toss the buffers.
Index: sys/mount.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/mount.h	(revision 241191)
+++ sys/mount.h	(working copy)
@@ -189,6 +189,8 @@
 #define	mnt_endzero	mnt_gjprovider
 	char		*mnt_gjprovider;	/* gjournal provider name */
 	struct lock	mnt_explock;		/* vfs_export walkers lock */
+	TAILQ_ENTRY(mount) mnt_upper_link;	/* (m) we in the all uppers */
+	TAILQ_HEAD(, mount) mnt_uppers;		/* (m) upper mounts over us*/
 };
=20
 /*
@@ -374,6 +376,10 @@
 #define	MNTK_NO_IOPF	0x00000100	/* Disallow page faults during reads
 					   and writes. Filesystem shall properly
 					   handle i/o state on EFAULT. */
+#define	MNTK_VGONE_UPPER	0x00000200
+#define	MNTK_VGONE_WAITER	0x00000200
+#define	MNTK_MARKER		0x00000400
+#define	MNTK_LOOKUP_EXCL_DOTDOT	0x00000800
 #define MNTK_NOASYNC	0x00800000	/* disable async */
 #define MNTK_UNMOUNT	0x01000000	/* unmount in progress */
 #define	MNTK_MWAIT	0x02000000	/* waiting for unmount to finish */
@@ -629,6 +635,7 @@
 typedef int vfs_sysctl_t(struct mount *mp, fsctlop_t op,
 		    struct sysctl_req *req);
 typedef void vfs_susp_clean_t(struct mount *mp);
+typedef void vfs_reclaim_lowervp_t(struct mount *mp, struct vnode *lowervp=
);
=20
 struct vfsops {
 	vfs_mount_t		*vfs_mount;
@@ -646,6 +653,7 @@
 	vfs_extattrctl_t	*vfs_extattrctl;
 	vfs_sysctl_t		*vfs_sysctl;
 	vfs_susp_clean_t	*vfs_susp_clean;
+	vfs_reclaim_lowervp_t	*vfs_reclaim_lowervp;
 };
=20
 vfs_statfs_t	__vfs_statfs;
@@ -671,6 +679,9 @@
 #define	VFS_SUSP_CLEAN(MP) \
 	({if (*(MP)->mnt_op->vfs_susp_clean !=3D NULL)		\
 	       (*(MP)->mnt_op->vfs_susp_clean)(MP); })
+#define	VFS_RECLAIM_LOWERVP(MP, VP)				\
+	({if (*(MP)->mnt_op->vfs_reclaim_lowervp !=3D NULL)	\
+		(*(MP)->mnt_op->vfs_reclaim_lowervp)((MP), (VP)); })
=20
 #define	VFS_NEEDSGIANT_(MP)						\
     ((MP) !=3D NULL && ((MP)->mnt_kern_flag & MNTK_MPSAFE) =3D=3D 0)

--Uaw16JuuybUwHkzF
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (FreeBSD)

iEYEARECAAYFAlBtUqoACgkQC3+MBN1Mb4hBqwCfRyj/Bye9dgTBFdfFiyYxjiNy
gTYAnjQFKbIFcYX89PZoLnPiW7y4hzzx
=Ew53
-----END PGP SIGNATURE-----

--Uaw16JuuybUwHkzF--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20121004091106.GF35915>