From owner-svn-src-head@FreeBSD.ORG Wed May 16 15:53:39 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3115B106564A; Wed, 16 May 2012 15:53:39 +0000 (UTC) (envelope-from pfg@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 11DF18FC16; Wed, 16 May 2012 15:53:39 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q4GFrcMQ049501; Wed, 16 May 2012 15:53:38 GMT (envelope-from pfg@svn.freebsd.org) Received: (from pfg@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q4GFrcls049498; Wed, 16 May 2012 15:53:38 GMT (envelope-from pfg@svn.freebsd.org) Message-Id: <201205161553.q4GFrcls049498@svn.freebsd.org> From: "Pedro F. Giffuni" Date: Wed, 16 May 2012 15:53:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r235508 - head/sys/fs/ext2fs X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 May 2012 15:53:39 -0000 Author: pfg Date: Wed May 16 15:53:38 2012 New Revision: 235508 URL: http://svn.freebsd.org/changeset/base/235508 Log: Fix a couple of issues that appear to be inherited from the old 8.x code: - If the lock cannot be acquired immediately unlocks 'bar' vnode and then locks both vnodes in order. - wrong vnode type panics from cache_enter_time after calls by ext2_lookup. The fix merges the fixes from ufs/ufs_lookup.c. Submitted by: Mateusz Guzik Approved by: jhb@ (mentor) Reviewed by: kib@ MFC after: 1 week Modified: head/sys/fs/ext2fs/ext2_lookup.c head/sys/fs/ext2fs/ext2_vnops.c Modified: head/sys/fs/ext2fs/ext2_lookup.c ============================================================================== --- head/sys/fs/ext2fs/ext2_lookup.c Wed May 16 15:17:51 2012 (r235507) +++ head/sys/fs/ext2fs/ext2_lookup.c Wed May 16 15:53:38 2012 (r235508) @@ -115,6 +115,8 @@ static u_char dt_to_ext2_ft[] = { static int ext2_dirbadentry(struct vnode *dp, struct ext2fs_direct_2 *de, int entryoffsetinblock); +static int ext2_lookup_ino(struct vnode *vdp, struct vnode **vpp, + struct componentname *cnp, ino_t *dd_ino); /* * Vnode op for reading directories. @@ -285,7 +287,14 @@ ext2_lookup(ap) struct componentname *a_cnp; } */ *ap; { - struct vnode *vdp; /* vnode for directory being searched */ + + return (ext2_lookup_ino(ap->a_dvp, ap->a_vpp, ap->a_cnp, NULL)); +} + +static int +ext2_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp, + ino_t *dd_ino) +{ struct inode *dp; /* inode for directory being searched */ struct buf *bp; /* a buffer of directory entries */ struct ext2fs_direct_2 *ep; /* the current directory entry */ @@ -305,22 +314,22 @@ ext2_lookup(ap) doff_t enduseful; /* pointer past last used dir slot */ u_long bmask; /* block offset mask */ int namlen, error; - struct vnode **vpp = ap->a_vpp; - struct componentname *cnp = ap->a_cnp; struct ucred *cred = cnp->cn_cred; int flags = cnp->cn_flags; int nameiop = cnp->cn_nameiop; - ino_t ino; + ino_t ino, ino1; int ltype; - int DIRBLKSIZ = VTOI(ap->a_dvp)->i_e2fs->e2fs_bsize; + int DIRBLKSIZ = VTOI(vdp)->i_e2fs->e2fs_bsize; + + if (vpp != NULL) + *vpp = NULL; - bp = NULL; - slotoffset = -1; - *vpp = NULL; - vdp = ap->a_dvp; dp = VTOI(vdp); bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; +restart: + bp = NULL; + slotoffset = -1; /* * We now have a segment name to search for, and a directory to search. @@ -536,10 +545,12 @@ searchloop: * Insert name into cache (as non-existent) if appropriate. */ if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) - cache_enter(vdp, *vpp, cnp); + cache_enter(vdp, NULL, cnp); return (ENOENT); found: + if (dd_ino != NULL) + *dd_ino = ino; if (numdirpasses == 2) nchstats.ncs_pass2++; /* @@ -582,6 +593,8 @@ found: dp->i_count = 0; else dp->i_count = dp->i_offset - prevoff; + if (dd_ino != NULL) + return (0); if (dp->i_number == ino) { VREF(vdp); *vpp = vdp; @@ -622,6 +635,8 @@ found: */ if (dp->i_number == ino) return (EISDIR); + if (dd_ino != NULL) + return (0); if ((error = VFS_VGET(vdp->v_mount, ino, LK_EXCLUSIVE, &tdp)) != 0) return (error); @@ -629,6 +644,8 @@ found: cnp->cn_flags |= SAVENAME; return (0); } + if (dd_ino != NULL) + return (0); /* * Step through the translation in the name. We do not `vput' the @@ -655,8 +672,27 @@ found: VOP_UNLOCK(pdp, 0); /* race to get the inode */ error = VFS_VGET(vdp->v_mount, ino, cnp->cn_lkflags, &tdp); vn_lock(pdp, ltype | LK_RETRY); - if (error != 0) + if (pdp->v_iflag & VI_DOOMED) { + if (error == 0) + vput(tdp); + error = ENOENT; + } + if (error) return (error); + /* + * Recheck that ".." entry in the vdp directory points + * to the inode we looked up before vdp lock was + * dropped. + */ + error = ext2_lookup_ino(pdp, NULL, cnp, &ino1); + if (error) { + vput(tdp); + return (error); + } + if (ino1 != ino) { + vput(tdp); + goto restart; + } *vpp = tdp; } else if (dp->i_number == ino) { VREF(vdp); /* we want ourself, ie "." */ Modified: head/sys/fs/ext2fs/ext2_vnops.c ============================================================================== --- head/sys/fs/ext2fs/ext2_vnops.c Wed May 16 15:17:51 2012 (r235507) +++ head/sys/fs/ext2fs/ext2_vnops.c Wed May 16 15:53:38 2012 (r235508) @@ -1336,7 +1336,11 @@ ext2_rmdir(ap) error = ext2_truncate(vp, (off_t)0, IO_SYNC, cnp->cn_cred, cnp->cn_thread); cache_purge(ITOV(ip)); - vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); + if (vn_lock(dvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) { + VOP_UNLOCK(vp, 0); + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + } out: return (error); }