From owner-p4-projects@FreeBSD.ORG Thu Oct 22 18:26:23 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id B8438106568D; Thu, 22 Oct 2009 18:26:23 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7CB5A106568B for ; Thu, 22 Oct 2009 18:26:23 +0000 (UTC) (envelope-from truncs@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 6A8ED8FC1E for ; Thu, 22 Oct 2009 18:26:23 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n9MIQNx3058201 for ; Thu, 22 Oct 2009 18:26:23 GMT (envelope-from truncs@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n9MIQNYB058199 for perforce@freebsd.org; Thu, 22 Oct 2009 18:26:23 GMT (envelope-from truncs@FreeBSD.org) Date: Thu, 22 Oct 2009 18:26:23 GMT Message-Id: <200910221826.n9MIQNYB058199@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to truncs@FreeBSD.org using -f From: Aditya Sarawgi To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 169688 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Oct 2009 18:26:24 -0000 http://p4web.freebsd.org/chv.cgi?CH=169688 Change 169688 by truncs@aditya on 2009/10/22 18:25:31 - Cache dp->i_offset in the local 'i_offset' variable for use in loop indexes so directory lookup becomes shared lock safe. In the modifying cases an exclusive lock is held here so the commit routine may rely on the state of i_offset. - Similarly handle i_diroff by fetching at the start and setting only once the operation is complete. Without the exclusive lock these are only considered hints. - Assert that an exclusive lock is held when we're preparing for a commit routine. - Honor the lock type request from lookup instead of always using exclusive locking. Affected files ... .. //depot/projects/soc2009/soc_ext2fs/src/sys/fs/ext2fs/ext2_lookup.c#9 edit Differences ... ==== //depot/projects/soc2009/soc_ext2fs/src/sys/fs/ext2fs/ext2_lookup.c#9 (text+ko) ==== @@ -298,6 +298,8 @@ enum {NONE, COMPACT, FOUND} slotstatus; doff_t slotoffset; /* offset of area with free space */ int slotsize; /* size of area at slotoffset */ + doff_t i_diroff; /* cached i_diroff value */ + doff_t i_offset; /* cached i_offset value */ int slotfreespace; /* amount of space free in slot */ int slotneeded; /* size of the entry we're seeking */ int numdirpasses; /* strategy for directory search */ @@ -314,6 +316,7 @@ int flags = cnp->cn_flags; int nameiop = cnp->cn_nameiop; ino_t ino; + int ltype; int DIRBLKSIZ = VTOI(ap->a_dvp)->i_e2fs->e2fs_bsize; @@ -333,6 +336,7 @@ * case it doesn't already exist. */ ino = 0; + i_diroff = dp->i_diroff; slotstatus = FOUND; slotfreespace = slotsize = slotneeded = 0; if ((nameiop == CREATE || nameiop == RENAME) && @@ -356,34 +360,34 @@ * of simplicity. */ bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; - if (nameiop != LOOKUP || dp->i_diroff == 0 || - dp->i_diroff > dp->i_size) { + if (nameiop != LOOKUP || i_diroff == 0 || + i_diroff > dp->i_size) { entryoffsetinblock = 0; - dp->i_offset = 0; + i_offset = 0; numdirpasses = 1; } else { - dp->i_offset = dp->i_diroff; - if ((entryoffsetinblock = dp->i_offset & bmask) && - (error = ext2_blkatoff(vdp, (off_t)dp->i_offset, NULL, + i_offset = i_diroff; + if ((entryoffsetinblock = i_offset & bmask) && + (error = ext2_blkatoff(vdp, (off_t)i_offset, NULL, &bp))) return (error); numdirpasses = 2; nchstats.ncs_2passes++; } - prevoff = dp->i_offset; + prevoff = i_offset; endsearch = roundup2(dp->i_size, DIRBLKSIZ); enduseful = 0; searchloop: - while (dp->i_offset < endsearch) { + while (i_offset < endsearch) { /* * If necessary, get the next directory block. */ - if ((dp->i_offset & bmask) == 0) { + if ((i_offset & bmask) == 0) { if (bp != NULL) brelse(bp); if ((error = - ext2_blkatoff(vdp, (off_t)dp->i_offset, NULL, + ext2_blkatoff(vdp, (off_t)i_offset, NULL, &bp)) != 0) return (error); entryoffsetinblock = 0; @@ -409,9 +413,9 @@ if (ep->e2d_reclen == 0 || (dirchk && ext2_dirbadentry(vdp, ep, entryoffsetinblock))) { int i; - ext2_dirbad(dp, dp->i_offset, "mangled entry"); + ext2_dirbad(dp, i_offset, "mangled entry"); i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)); - dp->i_offset += i; + i_offset += i; entryoffsetinblock += i; continue; } @@ -430,15 +434,15 @@ if (size > 0) { if (size >= slotneeded) { slotstatus = FOUND; - slotoffset = dp->i_offset; + slotoffset = i_offset; slotsize = ep->e2d_reclen; } else if (slotstatus == NONE) { slotfreespace += size; if (slotoffset == -1) - slotoffset = dp->i_offset; + slotoffset = i_offset; if (slotfreespace >= slotneeded) { slotstatus = COMPACT; - slotsize = dp->i_offset + + slotsize = i_offset + ep->e2d_reclen - slotoffset; } } @@ -462,11 +466,11 @@ goto found; } } - prevoff = dp->i_offset; - dp->i_offset += ep->e2d_reclen; + prevoff = i_offset; + i_offset += ep->e2d_reclen; entryoffsetinblock += ep->e2d_reclen; if (ep->e2d_ino) - enduseful = dp->i_offset; + enduseful = i_offset; } /* notfound: */ /* @@ -475,10 +479,11 @@ */ if (numdirpasses == 2) { numdirpasses--; - dp->i_offset = 0; - endsearch = dp->i_diroff; + i_offset = 0; + endsearch = i_diroff; goto searchloop; } + dp->i_offset = i_offset; if (bp != NULL) brelse(bp); /* @@ -547,7 +552,7 @@ */ if (entryoffsetinblock + EXT2_DIR_REC_LEN(ep->e2d_namlen) > dp->i_size) { - ext2_dirbad(dp, dp->i_offset, "i_size too small"); + ext2_dirbad(dp, i_offset, "i_size too small"); dp->i_size = entryoffsetinblock+EXT2_DIR_REC_LEN(ep->e2d_namlen); dp->i_flag |= IN_CHANGE | IN_UPDATE; } @@ -559,8 +564,8 @@ * in the cache as to where the entry was found. */ if ((flags & ISLASTCN) && nameiop == LOOKUP) - dp->i_diroff = dp->i_offset &~ (DIRBLKSIZ - 1); - + dp->i_diroff = i_offset &~ (DIRBLKSIZ - 1); + dp->i_offset = i_offset; /* * If deleting, and at end of pathname, return * parameters which can be used to remove file. @@ -650,14 +655,26 @@ */ pdp = vdp; if (flags & ISDOTDOT) { + ltype = VOP_ISLOCKED(pdp); VOP_UNLOCK(pdp, 0); /* race to get the inode */ error = VFS_VGET(vdp->v_mount, ino, LK_EXCLUSIVE, &tdp); - vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY); + vn_lock(pdp, ltype | LK_RETRY); if (error != 0) return (error); *vpp = tdp; } else if (dp->i_number == ino) { VREF(vdp); /* we want ourself, ie "." */ + /* + * When we lookup "." we still can be asked to lock it + * differently. + */ + ltype = cnp->cn_lkflags & LK_TYPE_MASK; + if (ltype != VOP_ISLOCKED(vdp)) { + if (ltype == LK_EXCLUSIVE) + vn_lock(vdp, LK_UPGRADE | LK_RETRY); + else /* if (ltype == LK_SHARED) */ + vn_lock(vdp, LK_DOWNGRADE | LK_RETRY); + } *vpp = vdp; } else { if ((error = VFS_VGET(vdp->v_mount, ino, LK_EXCLUSIVE,