Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/ufs/ufs/ufs_lookup.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/ufs/ufs/ufs_lookup.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.83 retrieving revision 1.98.4.2 diff -u -p -r1.83 -r1.98.4.2 --- src/sys/ufs/ufs/ufs_lookup.c 2007/01/19 14:49:13 1.83 +++ src/sys/ufs/ufs/ufs_lookup.c 2008/12/13 01:15:41 1.98.4.2 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_lookup.c,v 1.83 2007/01/19 14:49:13 hannken Exp $ */ +/* $NetBSD: ufs_lookup.c,v 1.98.4.2 2008/12/13 01:15:41 haad Exp $ */ /* * Copyright (c) 1989, 1993 @@ -37,10 +37,11 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ufs_lookup.c,v 1.83 2007/01/19 14:49:13 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ufs_lookup.c,v 1.98.4.2 2008/12/13 01:15:41 haad Exp $"); #ifdef _KERNEL_OPT #include "opt_ffs.h" +#include "fs_ffs.h" #endif #include @@ -53,7 +54,10 @@ __KERNEL_RCSID(0, "$NetBSD: ufs_lookup.c #include #include #include +#include #include +#include +#include #include #include @@ -63,8 +67,7 @@ __KERNEL_RCSID(0, "$NetBSD: ufs_lookup.c #include #include #include - -#include "fs_ffs.h" +#include #ifdef DIAGNOSTIC int dirchk = 1; @@ -152,11 +155,11 @@ ufs_lookup(void *v) /* * Check accessiblity of directory. */ - if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_lwp)) != 0) + if ((error = VOP_ACCESS(vdp, VEXEC, cred)) != 0) return (error); if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) && - (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) + (nameiop == DELETE || nameiop == RENAME)) return (EROFS); /* @@ -170,8 +173,7 @@ ufs_lookup(void *v) return (error); } - if ((error = fstrans_start(vdp->v_mount, fstrans_shared)) != 0) - return error; + fstrans_start(vdp->v_mount, FSTRANS_SHARED); /* * Suppress search for slots unless creating @@ -247,7 +249,8 @@ ufs_lookup(void *v) } else { dp->i_offset = dp->i_diroff; if ((entryoffsetinblock = dp->i_offset & bmask) && - (error = ufs_blkatoff(vdp, (off_t)dp->i_offset, NULL, &bp))) + (error = ufs_blkatoff(vdp, (off_t)dp->i_offset, + NULL, &bp, false))) goto out; numdirpasses = 2; nchstats.ncs_2passes++; @@ -259,21 +262,21 @@ ufs_lookup(void *v) searchloop: while (dp->i_offset < endsearch) { if (curcpu()->ci_schedstate.spc_flags & SPCF_SHOULDYIELD) - preempt(1); + preempt(); /* * If necessary, get the next directory block. */ if ((dp->i_offset & bmask) == 0) { if (bp != NULL) - brelse(bp); + brelse(bp, 0); error = ufs_blkatoff(vdp, (off_t)dp->i_offset, NULL, - &bp); + &bp, false); if (error) goto out; entryoffsetinblock = 0; } /* - * If still looking for a slot, and at a DIRBLKSIZE + * If still looking for a slot, and at a DIRBLKSIZ * boundary, have to start looking for free space again. */ if (slotstatus == NONE && @@ -409,7 +412,7 @@ notfound: goto searchloop; } if (bp != NULL) - brelse(bp); + brelse(bp, 0); /* * If creating, and at end of pathname and current * directory has not been removed, then can consider @@ -424,7 +427,7 @@ notfound: * Access for write is interpreted as allowing * creation of files in the directory. */ - error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_lwp); + error = VOP_ACCESS(vdp, VWRITE, cred); if (error) goto out; /* @@ -493,8 +496,9 @@ found: dp->i_size = dp->i_offset + DIRSIZ(FSFMT(vdp), ep, needswap); DIP_ASSIGN(dp, size, dp->i_size); dp->i_flag |= IN_CHANGE | IN_UPDATE; + UFS_WAPBL_UPDATE(vdp, NULL, NULL, UPDATE_DIROP); } - brelse(bp); + brelse(bp, 0); /* * Found component in pathname. @@ -513,7 +517,7 @@ found: /* * Write access to directory required to delete files. */ - error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_lwp); + error = VOP_ACCESS(vdp, VWRITE, cred); if (error) goto out; /* @@ -566,7 +570,7 @@ found: * regular file, or empty directory. */ if (nameiop == RENAME && (flags & ISLASTCN)) { - error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_lwp); + error = VOP_ACCESS(vdp, VWRITE, cred); if (error) goto out; /* @@ -688,11 +692,12 @@ ufs_dirbadentry(struct vnode *dp, struct DIRSIZ(FSFMT(dp), ep, needswap) || namlen > FFS_MAXNAMLEN) { /*return (1); */ - printf("First bad, reclen=%x, DIRSIZ=%lu, namlen=%d, flags=%x " - "entryoffsetinblock=%d, dirblksiz = %d\n", + printf("First bad, reclen=%#x, DIRSIZ=%lu, namlen=%d, " + "flags=%#x, entryoffsetinblock=%d, dirblksiz = %d\n", ufs_rw16(ep->d_reclen, needswap), (u_long)DIRSIZ(FSFMT(dp), ep, needswap), - namlen, dp->v_mount->mnt_flag, entryoffsetinblock,dirblksiz); + namlen, dp->v_mount->mnt_flag, entryoffsetinblock, + dirblksiz); goto bad; } if (ep->d_ino == 0) @@ -760,9 +765,11 @@ ufs_direnter(struct vnode *dvp, struct v const int needswap = UFS_MPNEEDSWAP(ump); int dirblksiz = ump->um_dirblksiz; + UFS_WAPBL_JLOCK_ASSERT(dvp->v_mount); + error = 0; cr = cnp->cn_cred; - l = cnp->cn_lwp; + l = curlwp; dp = VTOI(dvp); newentrysize = DIRSIZ(0, dirp, 0); @@ -803,8 +810,7 @@ ufs_direnter(struct vnode *dvp, struct v } } blkoff = dp->i_offset & (ump->um_mountp->mnt_stat.f_iosize - 1); - memcpy((caddr_t)bp->b_data + blkoff, (caddr_t)dirp, - newentrysize); + memcpy((char *)bp->b_data + blkoff, dirp, newentrysize); #ifdef UFS_DIRHASH if (dp->i_dirhash != NULL) { ufsdirhash_newblk(dp, dp->i_offset); @@ -823,7 +829,7 @@ ufs_direnter(struct vnode *dvp, struct v blkoff += dirblksiz; while (blkoff < bp->b_bcount) { ((struct direct *) - (bp->b_data + blkoff))->d_reclen = dirblksiz; + ((char *)bp->b_data + blkoff))->d_reclen = dirblksiz; blkoff += dirblksiz; } if (softdep_setup_directory_add(bp, dp, dp->i_offset, @@ -847,7 +853,7 @@ ufs_direnter(struct vnode *dvp, struct v return (error); if (tvp != NULL) VOP_UNLOCK(tvp, 0); - error = VOP_FSYNC(dvp, l->l_cred, FSYNC_WAIT, 0, 0, l); + error = VOP_FSYNC(dvp, l->l_cred, FSYNC_WAIT, 0, 0); if (tvp != 0) vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); return (error); @@ -873,7 +879,7 @@ ufs_direnter(struct vnode *dvp, struct v /* * Increase size of directory if entry eats into new space. * This should never push the size past a new multiple of - * DIRBLKSIZE. + * DIRBLKSIZ. * * N.B. - THIS IS AN ARTIFACT OF 4.2 AND SHOULD NEVER HAPPEN. */ @@ -881,11 +887,12 @@ ufs_direnter(struct vnode *dvp, struct v dp->i_size = dp->i_offset + dp->i_count; DIP_ASSIGN(dp, size, dp->i_size); dp->i_flag |= IN_CHANGE | IN_UPDATE; + UFS_WAPBL_UPDATE(dvp, NULL, NULL, UPDATE_DIROP); } /* * Get the block containing the space for the new directory entry. */ - error = ufs_blkatoff(dvp, (off_t)dp->i_offset, &dirbuf, &bp); + error = ufs_blkatoff(dvp, (off_t)dp->i_offset, &dirbuf, &bp, true); if (error) { if (DOINGSOFTDEP(dvp) && newdirbp != NULL) bdwrite(newdirbp); @@ -898,8 +905,7 @@ ufs_direnter(struct vnode *dvp, struct v * dp->i_offset + dp->i_count would yield the space. */ ep = (struct direct *)dirbuf; - dsize = ufs_rw32(ep->d_ino, needswap) ? - DIRSIZ(FSFMT(dvp), ep, needswap) : 0; + dsize = (ep->d_ino != 0) ? DIRSIZ(FSFMT(dvp), ep, needswap) : 0; spacefree = ufs_rw16(ep->d_reclen, needswap) - dsize; for (loc = ufs_rw16(ep->d_reclen, needswap); loc < dp->i_count; ) { uint16_t reclen; @@ -936,9 +942,9 @@ ufs_direnter(struct vnode *dvp, struct v #endif if (DOINGSOFTDEP(dvp)) softdep_change_directoryentry_offset(dp, dirbuf, - (caddr_t)nep, (caddr_t)ep, dsize); + (void *)nep, (void *)ep, dsize); else - memcpy((caddr_t)ep, (caddr_t)nep, dsize); + memcpy((void *)ep, (void *)nep, dsize); } /* * Here, `ep' points to a directory entry containing `dsize' in-use @@ -980,7 +986,7 @@ ufs_direnter(struct vnode *dvp, struct v dirp->d_reclen == spacefree)) ufsdirhash_add(dp, dirp, dp->i_offset + ((char *)ep - dirbuf)); #endif - memcpy((caddr_t)ep, (caddr_t)dirp, (u_int)newentrysize); + memcpy((void *)ep, (void *)dirp, (u_int)newentrysize); #ifdef UFS_DIRHASH if (dp->i_dirhash != NULL) ufsdirhash_checkblock(dp, dirbuf - @@ -989,7 +995,7 @@ ufs_direnter(struct vnode *dvp, struct v #endif if (DOINGSOFTDEP(dvp)) { softdep_setup_directory_add(bp, dp, - dp->i_offset + (caddr_t)ep - dirbuf, + dp->i_offset + (char *)ep - dirbuf, ufs_rw32(dirp->d_ino, needswap), newdirbp, 0); bdwrite(bp); } else { @@ -1010,10 +1016,11 @@ ufs_direnter(struct vnode *dvp, struct v if (dp->i_dirhash != NULL) ufsdirhash_dirtrunc(dp, dp->i_endoff); #endif - (void) UFS_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, cr, l); + (void) UFS_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, cr); if (DOINGSOFTDEP(dvp) && (tvp != NULL)) vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); } + UFS_WAPBL_UPDATE(dvp, NULL, NULL, UPDATE_DIROP); return (error); } @@ -1040,12 +1047,14 @@ ufs_dirremove(struct vnode *dvp, struct const int needswap = UFS_MPNEEDSWAP(dp->i_ump); #endif + UFS_WAPBL_JLOCK_ASSERT(dvp->v_mount); + if (flags & DOWHITEOUT) { /* * Whiteout entry: set d_ino to WINO. */ error = ufs_blkatoff(dvp, (off_t)dp->i_offset, (void *)&ep, - &bp); + &bp, true); if (error) return (error); ep->d_ino = ufs_rw32(WINO, needswap); @@ -1054,7 +1063,7 @@ ufs_dirremove(struct vnode *dvp, struct } if ((error = ufs_blkatoff(dvp, - (off_t)(dp->i_offset - dp->i_count), (void *)&ep, &bp)) != 0) + (off_t)(dp->i_offset - dp->i_count), (void *)&ep, &bp, true)) != 0) return (error); #ifdef UFS_DIRHASH @@ -1064,7 +1073,8 @@ ufs_dirremove(struct vnode *dvp, struct */ if (dp->i_dirhash != NULL) ufsdirhash_remove(dp, (dp->i_count == 0) ? ep : - (struct direct *)((char *)ep + ep->d_reclen), dp->i_offset); + (struct direct *)((char *)ep + + ufs_rw16(ep->d_reclen, needswap)), dp->i_offset); #endif if (dp->i_count == 0) { @@ -1104,6 +1114,7 @@ out: ip->i_nlink--; DIP_ASSIGN(ip, nlink, ip->i_nlink); ip->i_flag |= IN_CHANGE; + UFS_WAPBL_UPDATE(ITOV(ip), NULL, NULL, 0); } error = VOP_BWRITE(bp); } @@ -1117,6 +1128,7 @@ out: if (ip != 0 && (ip->i_flags & SF_SNAPSHOT) != 0 && ip->i_ffs_effnlink == 0) ffs_snapgone(ip); + UFS_WAPBL_UPDATE(dvp, NULL, NULL, 0); #endif return (error); } @@ -1135,7 +1147,7 @@ ufs_dirrewrite(struct inode *dp, struct struct vnode *vdp = ITOV(dp); int error; - error = ufs_blkatoff(vdp, (off_t)dp->i_offset, (void *)&ep, &bp); + error = ufs_blkatoff(vdp, (off_t)dp->i_offset, (void *)&ep, &bp, true); if (error) return (error); ep->d_ino = ufs_rw32(newinum, UFS_MPNEEDSWAP(dp->i_ump)); @@ -1150,6 +1162,7 @@ ufs_dirrewrite(struct inode *dp, struct oip->i_nlink--; DIP_ASSIGN(oip, nlink, oip->i_nlink); oip->i_flag |= IN_CHANGE; + UFS_WAPBL_UPDATE(ITOV(oip), NULL, NULL, UPDATE_DIROP); error = VOP_BWRITE(bp); } dp->i_flag |= iflags; @@ -1161,6 +1174,7 @@ ufs_dirrewrite(struct inode *dp, struct */ if ((oip->i_flags & SF_SNAPSHOT) != 0 && oip->i_ffs_effnlink == 0) ffs_snapgone(oip); + UFS_WAPBL_UPDATE(vdp, NULL, NULL, UPDATE_DIROP); #endif return (error); } @@ -1187,7 +1201,7 @@ ufs_dirempty(struct inode *ip, ino_t par for (off = 0; off < ip->i_size; off += ufs_rw16(dp->d_reclen, needswap)) { - error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)dp, MINDIRSIZ, off, + error = vn_rdwr(UIO_READ, ITOV(ip), (void *)dp, MINDIRSIZ, off, UIO_SYSSPACE, IO_NODELOCKED, cred, &count, NULL); /* * Since we read MINDIRSIZ, residual must @@ -1261,7 +1275,7 @@ ufs_checkpath(struct inode *source, stru error = ENOTDIR; break; } - error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirbuf, + error = vn_rdwr(UIO_READ, vp, (void *)&dirbuf, sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, IO_NODELOCKED, cred, NULL, NULL); if (error != 0) @@ -1312,29 +1326,33 @@ int ufs_dirrablks = UFS_DIRRABLKS; /* * ufs_blkatoff: Return buffer with the contents of block "offset" from * the beginning of directory "vp". If "res" is non-zero, fill it in with - * a pointer to the remaining space in the directory. + * a pointer to the remaining space in the directory. If the caller intends + * to modify the buffer returned, "modify" must be true. */ int -ufs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp) +ufs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp, + bool modify) { struct inode *ip; struct buf *bp; daddr_t lbn; - int error; const int dirrablks = ufs_dirrablks; - daddr_t blks[1 + dirrablks]; - int blksizes[1 + dirrablks]; - int run; + daddr_t *blks; + int *blksizes; + int run, error; struct mount *mp = vp->v_mount; const int bshift = mp->mnt_fs_bshift; const int bsize = 1 << bshift; off_t eof; + blks = kmem_alloc((1 + dirrablks) * sizeof(daddr_t), KM_SLEEP); + blksizes = kmem_alloc((1 + dirrablks) * sizeof(int), KM_SLEEP); ip = VTOI(vp); KASSERT(vp->v_size == ip->i_size); GOP_SIZE(vp, vp->v_size, &eof, 0); lbn = offset >> bshift; + for (run = 0; run <= dirrablks;) { const off_t curoff = lbn << bshift; const int size = MIN(eof - curoff, bsize); @@ -1353,15 +1371,19 @@ ufs_blkatoff(struct vnode *vp, off_t off } KASSERT(run >= 1); error = breadn(vp, blks[0], blksizes[0], &blks[1], &blksizes[1], - run - 1, NOCRED, &bp); + run - 1, NOCRED, (modify ? B_MODIFY : 0), &bp); if (error != 0) { - brelse(bp); + brelse(bp, 0); *bpp = NULL; - return error; + goto out; } if (res) { *res = (char *)bp->b_data + (offset & (bsize - 1)); } *bpp = bp; - return 0; + + out: + kmem_free(blks, (1 + dirrablks) * sizeof(daddr_t)); + kmem_free(blksizes, (1 + dirrablks) * sizeof(int)); + return error; }