From owner-svn-src-stable@FreeBSD.ORG Fri Aug 22 07:09:55 2014 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 348BF661; Fri, 22 Aug 2014 07:09:55 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 141C83CEE; Fri, 22 Aug 2014 07:09:55 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s7M79s9Y063645; Fri, 22 Aug 2014 07:09:54 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s7M79sKx063644; Fri, 22 Aug 2014 07:09:54 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201408220709.s7M79sKx063644@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Fri, 22 Aug 2014 07:09:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r270319 - stable/10/sys/fs/nullfs X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 22 Aug 2014 07:09:55 -0000 Author: kib Date: Fri Aug 22 07:09:54 2014 New Revision: 270319 URL: http://svnweb.freebsd.org/changeset/base/270319 Log: MFC r269708: Unlock ldvp and lock dvp to compensate for possible ldvp unlock in lower VOP_LOOKUP() and dvp reclamation. Use cached value of dvp->v_mount. Modified: stable/10/sys/fs/nullfs/null_vnops.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/fs/nullfs/null_vnops.c ============================================================================== --- stable/10/sys/fs/nullfs/null_vnops.c Fri Aug 22 05:03:30 2014 (r270318) +++ stable/10/sys/fs/nullfs/null_vnops.c Fri Aug 22 07:09:54 2014 (r270319) @@ -361,9 +361,11 @@ null_lookup(struct vop_lookup_args *ap) struct vnode *dvp = ap->a_dvp; int flags = cnp->cn_flags; struct vnode *vp, *ldvp, *lvp; + struct mount *mp; int error; - if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && + mp = dvp->v_mount; + if ((flags & ISLASTCN) != 0 && (mp->mnt_flag & MNT_RDONLY) != 0 && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) return (EROFS); /* @@ -376,9 +378,43 @@ null_lookup(struct vop_lookup_args *ap) ((dvp->v_vflag & VV_ROOT) != 0 && (flags & ISDOTDOT) == 0), ("ldvp %p fl %#x dvp %p fl %#x flags %#x", ldvp, ldvp->v_vflag, dvp, dvp->v_vflag, flags)); + + /* + * Hold ldvp. The reference on it, owned by dvp, is lost in + * case of dvp reclamation, and we need ldvp to move our lock + * from ldvp to dvp. + */ + vhold(ldvp); + error = VOP_LOOKUP(ldvp, &lvp, cnp); - if (error == EJUSTRETURN && (flags & ISLASTCN) && - (dvp->v_mount->mnt_flag & MNT_RDONLY) && + + /* + * VOP_LOOKUP() on lower vnode may unlock ldvp, which allows + * dvp to be reclaimed due to shared v_vnlock. Check for the + * doomed state and return error. + */ + if ((error == 0 || error == EJUSTRETURN) && + (dvp->v_iflag & VI_DOOMED) != 0) { + error = ENOENT; + if (lvp != NULL) + vput(lvp); + + /* + * If vgone() did reclaimed dvp before curthread + * relocked ldvp, the locks of dvp and ldpv are no + * longer shared. In this case, relock of ldvp in + * lower fs VOP_LOOKUP() does not restore the locking + * state of dvp. Compensate for this by unlocking + * ldvp and locking dvp, which is also correct if the + * locks are still shared. + */ + VOP_UNLOCK(ldvp, 0); + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); + } + vdrop(ldvp); + + if (error == EJUSTRETURN && (flags & ISLASTCN) != 0 && + (mp->mnt_flag & MNT_RDONLY) != 0 && (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)) error = EROFS; @@ -388,7 +424,7 @@ null_lookup(struct vop_lookup_args *ap) VREF(dvp); vrele(lvp); } else { - error = null_nodeget(dvp->v_mount, lvp, &vp); + error = null_nodeget(mp, lvp, &vp); if (error == 0) *ap->a_vpp = vp; }