diff options
author | John Dyson <dyson@FreeBSD.org> | 1997-02-10 02:22:35 +0000 |
---|---|---|
committer | John Dyson <dyson@FreeBSD.org> | 1997-02-10 02:22:35 +0000 |
commit | 996c772f581f5624846dcd8470ca6860c1678b7c (patch) | |
tree | 88a944de263165091f0a18abeedbaaccec532407 /sys/isofs/cd9660/cd9660_lookup.c | |
parent | d243e2f7f456304830e7f832629bc24c504c2385 (diff) | |
download | src-996c772f581f5624846dcd8470ca6860c1678b7c.tar.gz src-996c772f581f5624846dcd8470ca6860c1678b7c.zip |
This is the kernel Lite/2 commit. There are some requisite userland
changes, so don't expect to be able to run the kernel as-is (very well)
without the appropriate Lite/2 userland changes.
The system boots and can mount UFS filesystems.
Untested: ext2fs, msdosfs, NFS
Known problems: Incorrect Berkeley ID strings in some files.
Mount_std mounts will not work until the getfsent
library routine is changed.
Reviewed by: various people
Submitted by: Jeffery Hsu <hsu@freebsd.org>
Notes
Notes:
svn path=/head/; revision=22521
Diffstat (limited to 'sys/isofs/cd9660/cd9660_lookup.c')
-rw-r--r-- | sys/isofs/cd9660/cd9660_lookup.c | 173 |
1 files changed, 96 insertions, 77 deletions
diff --git a/sys/isofs/cd9660/cd9660_lookup.c b/sys/isofs/cd9660/cd9660_lookup.c index 6e85a8137bd2..a7e38bb36b80 100644 --- a/sys/isofs/cd9660/cd9660_lookup.c +++ b/sys/isofs/cd9660/cd9660_lookup.c @@ -108,8 +108,9 @@ cd9660_lookup(ap) int saveoffset = 0; /* offset of last directory entry in dir */ int numdirpasses; /* strategy for directory search */ doff_t endsearch; /* offset to end directory search */ - struct iso_node *pdp; /* saved dp during symlink work */ - struct iso_node *tdp; /* returned by iget */ + struct vnode *pdp; /* saved dp during symlink work */ + struct vnode *tdp; /* returned by cd9660_vget_internal */ + u_long bmask; /* block offset mask */ int lockparent; /* 1 => lockparent flag is set */ int wantparent; /* 1 => wantparent or lockparent flag */ int error; @@ -126,6 +127,7 @@ cd9660_lookup(ap) struct ucred *cred = cnp->cn_cred; int flags = cnp->cn_flags; int nameiop = cnp->cn_nameiop; + struct proc *p = cnp->cn_proc; bp = NULL; *vpp = NULL; @@ -139,13 +141,13 @@ cd9660_lookup(ap) * Check accessiblity of directory. */ if (vdp->v_type != VDIR) - return (ENOTDIR); - if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc))) + return (ENOTDIR); + if (error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)) return (error); if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) return (EROFS); - + /* * We now have a segment name to search for, and a directory to search. * @@ -160,29 +162,29 @@ cd9660_lookup(ap) return (error); #ifdef PARANOID if ((vdp->v_flag & VROOT) && (flags & ISDOTDOT)) - panic("ufs_lookup: .. through root"); + panic("cd9660_lookup: .. through root"); #endif /* * Get the next vnode in the path. * See comment below starting `Step through' for * an explaination of the locking protocol. */ - pdp = dp; + pdp = vdp; dp = VTOI(*vpp); vdp = *vpp; vpid = vdp->v_id; - if (pdp == dp) { + if (pdp == vdp) { VREF(vdp); error = 0; } else if (flags & ISDOTDOT) { - ISO_IUNLOCK(pdp); - error = vget(vdp, 1); + VOP_UNLOCK(pdp, 0, p); + error = vget(vdp, LK_EXCLUSIVE, p); if (!error && lockparent && (flags & ISLASTCN)) - ISO_ILOCK(pdp); + error = vn_lock(pdp, LK_EXCLUSIVE, p); } else { - error = vget(vdp, 1); + error = vget(vdp, LK_EXCLUSIVE, p); if (!lockparent || error || !(flags & ISLASTCN)) - ISO_IUNLOCK(pdp); + VOP_UNLOCK(pdp, 0, p); } /* * Check that the capability number did not change @@ -191,13 +193,14 @@ cd9660_lookup(ap) if (!error) { if (vpid == vdp->v_id) return (0); - iso_iput(dp); - if (lockparent && pdp != dp && (flags & ISLASTCN)) - ISO_IUNLOCK(pdp); + vput(vdp); + if (lockparent && pdp != vdp && (flags & ISLASTCN)) + VOP_UNLOCK(pdp, 0, p); } - ISO_ILOCK(pdp); - dp = pdp; - vdp = ITOV(dp); + if (error = vn_lock(pdp, LK_EXCLUSIVE, p)) + return (error); + vdp = pdp; + dp = VTOI(pdp); *vpp = NULL; } @@ -223,6 +226,7 @@ cd9660_lookup(ap) * profiling time and hence has been removed in the interest * of simplicity. */ + bmask = imp->im_bmask; if (nameiop != LOOKUP || dp->i_diroff == 0 || dp->i_diroff > dp->i_size) { entryoffsetinblock = 0; @@ -230,16 +234,14 @@ cd9660_lookup(ap) numdirpasses = 1; } else { dp->i_offset = dp->i_diroff; - entryoffsetinblock = iso_blkoff(imp, dp->i_offset); - if (entryoffsetinblock != 0) { - if ((error = iso_blkatoff(dp, dp->i_offset, &bp))) + if ((entryoffsetinblock = dp->i_offset & bmask) && + (error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp))) return (error); - } numdirpasses = 2; iso_nchstats.ncs_2passes++; } - endsearch = roundup(dp->i_size, imp->logical_block_size); - + endsearch = dp->i_size; + searchloop: while (dp->i_offset < endsearch) { /* @@ -247,10 +249,11 @@ searchloop: * read the next directory block. * Release previous if it exists. */ - if (iso_blkoff(imp, dp->i_offset) == 0) { + if ((dp->i_offset & bmask) == 0) { if (bp != NULL) brelse(bp); - if ((error = iso_blkatoff(dp, dp->i_offset, &bp))) + if (error = + VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp)) return (error); entryoffsetinblock = 0; } @@ -258,13 +261,13 @@ searchloop: * Get pointer to next entry. */ ep = (struct iso_directory_record *) - (bp->b_un.b_addr + entryoffsetinblock); - - reclen = isonum_711 (ep->length); + ((char *)bp->b_data + entryoffsetinblock); + + reclen = isonum_711(ep->length); if (reclen == 0) { /* skip to next block, if any */ dp->i_offset = - roundup(dp->i_offset, imp->logical_block_size); + (dp->i_offset & ~bmask) + imp->logical_block_size; continue; } @@ -275,10 +278,7 @@ searchloop: if (entryoffsetinblock + reclen > imp->logical_block_size) /* entries are not allowed to cross boundaries */ break; - - /* - * Check for a name match. - */ + namelen = isonum_711(ep->name_len); isoflags = isonum_711(imp->iso_ftype == ISO_FTYPE_HIGH_SIERRA? &ep->date[6]: ep->flags); @@ -286,7 +286,10 @@ searchloop: if (reclen < ISO_DIRECTORY_RECORD_SIZE + namelen) /* illegal entry, stop */ break; - + + /* + * Check for a name match. + */ switch (imp->iso_ftype) { default: if (!(isoflags & 4) == !assoc) { @@ -297,10 +300,9 @@ searchloop: && ep->name[0] == ((flags & ISDOTDOT) ? 1 : 0)) { /* * Save directory entry's inode number and - * reclen in ndp->ni_ufs area, and release - * directory buffer. + * release directory buffer. */ - isodirino(&dp->i_ino,ep,imp); + dp->i_ino = isodirino(ep, imp); goto found; } if (namelen != 1 @@ -308,8 +310,8 @@ searchloop: goto notfound; } else if (!(res = isofncmp(name,len, ep->name,namelen))) { - if (isoflags & 2) - isodirino(&ino,ep,imp); + if (isonum_711(ep->flags)&2) + ino = isodirino(ep, imp); else ino = dbtob(bp->b_blkno) + entryoffsetinblock; @@ -326,7 +328,7 @@ searchloop: break; case ISO_FTYPE_RRIP: if (isonum_711(ep->flags)&2) - isodirino(&ino,ep,imp); + ino = isodirino(ep, imp); else ino = dbtob(bp->b_blkno) + entryoffsetinblock; dp->i_ino = ino; @@ -344,15 +346,17 @@ searchloop: foundino: dp->i_ino = ino; if (saveoffset != dp->i_offset) { - if (iso_lblkno(imp,dp->i_offset) - != iso_lblkno(imp,saveoffset)) { + if (lblkno(imp, dp->i_offset) != + lblkno(imp, saveoffset)) { if (bp != NULL) brelse(bp); - if ((error = iso_blkatoff(dp, saveoffset, &bp))) + if (error = VOP_BLKATOFF(vdp, + (off_t)saveoffset, NULL, &bp)) return (error); } - ep = (struct iso_directory_record *)(bp->b_un.b_addr - + iso_blkoff(imp,saveoffset)); + entryoffsetinblock = saveoffset & bmask; + ep = (struct iso_directory_record *) + ((char *)bp->b_data + entryoffsetinblock); dp->i_offset = saveoffset; } goto found; @@ -370,6 +374,7 @@ notfound: } if (bp != NULL) brelse(bp); + /* * Insert name into cache (as non-existent) if appropriate. */ @@ -382,9 +387,7 @@ notfound: found: if (numdirpasses == 2) iso_nchstats.ncs_pass2++; - if (bp != NULL) - brelse(bp); - + /* * Found component in pathname. * If the final component of path name, save information @@ -412,31 +415,39 @@ found: * work if the file system has any hard links other than ".." * that point backwards in the directory structure. */ - pdp = dp; + pdp = vdp; /* * If ino is different from dp->i_ino, * it's a relocated directory. */ if (flags & ISDOTDOT) { - ISO_IUNLOCK(pdp); /* race to get the inode */ - if ((error = iso_iget(dp,dp->i_ino, - dp->i_ino != ino, - &tdp,ep))) { - ISO_ILOCK(pdp); + VOP_UNLOCK(pdp, 0, p); /* race to get the inode */ + error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp, + dp->i_ino != ino, ep); + brelse(bp); + if (error) { + vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p); return (error); } - if (lockparent && (flags & ISLASTCN)) - ISO_ILOCK(pdp); - *vpp = ITOV(tdp); + if (lockparent && (flags & ISLASTCN) && + (error = vn_lock(pdp, LK_EXCLUSIVE, p))) { + vput(tdp); + return (error); + } + *vpp = tdp; } else if (dp->i_number == dp->i_ino) { + brelse(bp); VREF(vdp); /* we want ourself, ie "." */ *vpp = vdp; } else { - if ((error = iso_iget(dp,dp->i_ino,dp->i_ino!=ino,&tdp,ep))) + error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp, + dp->i_ino != ino, ep); + brelse(bp); + if (error) return (error); if (!lockparent || !(flags & ISLASTCN)) - ISO_IUNLOCK(pdp); - *vpp = ITOV(tdp); + VOP_UNLOCK(pdp, 0, p); + *vpp = tdp; } /* @@ -448,29 +459,37 @@ found: } /* - * Return buffer with contents of block "offset" - * from the beginning of directory "ip". If "res" - * is non-zero, fill it in with a pointer to the + * Return buffer with the contents of block "offset" from the beginning of + * directory "ip". If "res" is non-zero, fill it in with a pointer to the * remaining space in the directory. */ int -iso_blkatoff(ip, offset, bpp) - struct iso_node *ip; - doff_t offset; - struct buf **bpp; +cd9660_blkatoff(ap) + struct vop_blkatoff_args /* { + struct vnode *a_vp; + off_t a_offset; + char **a_res; + struct buf **a_bpp; + } */ *ap; { - register struct iso_mnt *imp = ip->i_mnt; - daddr_t lbn = iso_lblkno(imp,offset); - int bsize = iso_blksize(imp,ip,lbn); + struct iso_node *ip; + register struct iso_mnt *imp; struct buf *bp; - int error; + daddr_t lbn; + int bsize, error; - if ((error = bread(ITOV(ip),lbn,bsize,NOCRED,&bp))) { + ip = VTOI(ap->a_vp); + imp = ip->i_mnt; + lbn = lblkno(imp, ap->a_offset); + bsize = blksize(imp, ip, lbn); + + if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) { brelse(bp); - *bpp = 0; + *ap->a_bpp = NULL; return (error); } - *bpp = bp; - + if (ap->a_res) + *ap->a_res = (char *)bp->b_data + blkoff(imp, ap->a_offset); + *ap->a_bpp = bp; return (0); } |