From owner-freebsd-stable@FreeBSD.ORG Thu Oct 4 09:11:17 2012 Return-Path: Delivered-To: freebsd-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 89E22106566B for ; Thu, 4 Oct 2012 09:11:17 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from mail.zoral.com.ua (mx0.zoral.com.ua [91.193.166.200]) by mx1.freebsd.org (Postfix) with ESMTP id 8EA668FC29 for ; Thu, 4 Oct 2012 09:11:15 +0000 (UTC) Received: from skuns.kiev.zoral.com.ua (localhost [127.0.0.1]) by mail.zoral.com.ua (8.14.2/8.14.2) with ESMTP id q949BJ7c037688; Thu, 4 Oct 2012 12:11:19 +0300 (EEST) (envelope-from kostikbel@gmail.com) Received: from deviant.kiev.zoral.com.ua (kostik@localhost [127.0.0.1]) by deviant.kiev.zoral.com.ua (8.14.5/8.14.5) with ESMTP id q949B7wR075819; Thu, 4 Oct 2012 12:11:07 +0300 (EEST) (envelope-from kostikbel@gmail.com) Received: (from kostik@localhost) by deviant.kiev.zoral.com.ua (8.14.5/8.14.5/Submit) id q949B7nE075818; Thu, 4 Oct 2012 12:11:07 +0300 (EEST) (envelope-from kostikbel@gmail.com) X-Authentication-Warning: deviant.kiev.zoral.com.ua: kostik set sender to kostikbel@gmail.com using -f Date: Thu, 4 Oct 2012 12:11:07 +0300 From: Konstantin Belousov To: Norbert Aschendorff Message-ID: <20121004091106.GF35915@deviant.kiev.zoral.com.ua> 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> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="Uaw16JuuybUwHkzF" Content-Disposition: inline In-Reply-To: <506D474D.6090107@yahoo.de> User-Agent: Mutt/1.5.21 (2010-09-15) X-Virus-Scanned: clamav-milter 0.95.2 at skuns.kiev.zoral.com.ua X-Virus-Status: Clean X-Spam-Status: No, score=-4.0 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00 autolearn=ham version=3.2.5 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on skuns.kiev.zoral.com.ua Cc: freebsd-stable@freebsd.org Subject: Re: panic "Sleeping thread owns a non-sleepable lock" via cv_timedwait_signal, was "rsync over NFS" X-BeenThere: freebsd-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Production branch of FreeBSD source code List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 04 Oct 2012 09:11:17 -0000 --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--