summaryrefslogtreecommitdiffstats
path: root/sys/fs/cd9660/cd9660_lookup.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/cd9660/cd9660_lookup.c')
-rw-r--r--sys/fs/cd9660/cd9660_lookup.c173
1 files changed, 96 insertions, 77 deletions
diff --git a/sys/fs/cd9660/cd9660_lookup.c b/sys/fs/cd9660/cd9660_lookup.c
index 6e85a81..a7e38bb 100644
--- a/sys/fs/cd9660/cd9660_lookup.c
+++ b/sys/fs/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);
}
OpenPOWER on IntegriCloud