diff options
Diffstat (limited to 'sys/isofs/cd9660')
-rw-r--r-- | sys/isofs/cd9660/cd9660_lookup.c | 6 | ||||
-rw-r--r-- | sys/isofs/cd9660/cd9660_node.c | 18 | ||||
-rw-r--r-- | sys/isofs/cd9660/cd9660_node.h | 2 | ||||
-rw-r--r-- | sys/isofs/cd9660/cd9660_vfsops.c | 30 | ||||
-rw-r--r-- | sys/isofs/cd9660/iso.h | 2 |
5 files changed, 42 insertions, 16 deletions
diff --git a/sys/isofs/cd9660/cd9660_lookup.c b/sys/isofs/cd9660/cd9660_lookup.c index 706a7ae..da927e1 100644 --- a/sys/isofs/cd9660/cd9660_lookup.c +++ b/sys/isofs/cd9660/cd9660_lookup.c @@ -352,7 +352,8 @@ found: */ if (flags & ISDOTDOT) { VOP_UNLOCK(pdp, 0, td); /* race to get the inode */ - error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp, + error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, + LK_EXCLUSIVE, &tdp, dp->i_ino != ino, ep); brelse(bp); if (error) { @@ -373,7 +374,8 @@ found: VREF(vdp); /* we want ourself, ie "." */ *vpp = vdp; } else { - error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp, + error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, + LK_EXCLUSIVE, &tdp, dp->i_ino != ino, ep); brelse(bp); if (error) diff --git a/sys/isofs/cd9660/cd9660_node.c b/sys/isofs/cd9660/cd9660_node.c index 53ffeca..0060364 100644 --- a/sys/isofs/cd9660/cd9660_node.c +++ b/sys/isofs/cd9660/cd9660_node.c @@ -92,15 +92,19 @@ cd9660_uninit(vfsp) * Use the device/inum pair to find the incore inode, and return a pointer * to it. If it is in core, but locked, wait for it. */ -struct vnode * -cd9660_ihashget(dev, inum) +int +cd9660_ihashget(dev, inum, flags, vpp) dev_t dev; ino_t inum; + int flags; + struct vnode **vpp; { struct thread *td = curthread; /* XXX */ struct iso_node *ip; struct vnode *vp; + int error; + *vpp = NULL; loop: mtx_lock(&cd9660_ihash_mtx); for (ip = isohashtbl[INOHASH(dev, inum)]; ip; ip = ip->i_next) { @@ -108,13 +112,17 @@ loop: vp = ITOV(ip); mtx_lock(&vp->v_interlock); mtx_unlock(&cd9660_ihash_mtx); - if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) + error = vget(vp, flags | LK_INTERLOCK, td); + if (error == ENOENT) goto loop; - return (vp); + if (error) + return (error); + *vpp = vp; + return (0); } } mtx_unlock(&cd9660_ihash_mtx); - return (NULL); + return (0); } /* diff --git a/sys/isofs/cd9660/cd9660_node.h b/sys/isofs/cd9660/cd9660_node.h index 100c08e..2a0d7ef 100644 --- a/sys/isofs/cd9660/cd9660_node.h +++ b/sys/isofs/cd9660/cd9660_node.h @@ -117,7 +117,7 @@ void cd9660_defattr __P((struct iso_directory_record *, struct iso_node *, struct buf *, enum ISO_FTYPE)); void cd9660_deftstamp __P((struct iso_directory_record *, struct iso_node *, struct buf *, enum ISO_FTYPE)); -struct vnode *cd9660_ihashget __P((dev_t, ino_t)); +int cd9660_ihashget __P((dev_t, ino_t, int, struct vnode **)); void cd9660_ihashins __P((struct iso_node *)); int cd9660_tstamp_conv7 __P((u_char *, struct timespec *, enum ISO_FTYPE)); int cd9660_tstamp_conv17 __P((u_char *, struct timespec *)); diff --git a/sys/isofs/cd9660/cd9660_vfsops.c b/sys/isofs/cd9660/cd9660_vfsops.c index 1e3719d..60a7b38 100644 --- a/sys/isofs/cd9660/cd9660_vfsops.c +++ b/sys/isofs/cd9660/cd9660_vfsops.c @@ -69,7 +69,7 @@ static int cd9660_mount __P((struct mount *, static int cd9660_unmount __P((struct mount *, int, struct thread *)); static int cd9660_root __P((struct mount *, struct vnode **)); static int cd9660_statfs __P((struct mount *, struct statfs *, struct thread *)); -static int cd9660_vget __P((struct mount *, ino_t, struct vnode **)); +static int cd9660_vget __P((struct mount *, ino_t, int, struct vnode **)); static int cd9660_fhtovp __P((struct mount *, struct fid *, struct vnode **)); static int cd9660_vptofh __P((struct vnode *, struct fid *)); @@ -578,7 +578,7 @@ cd9660_root(mp, vpp) * With RRIP we must use the `.' entry of the root directory. * Simply tell vget, that it's a relocated directory. */ - return (cd9660_vget_internal(mp, ino, vpp, + return (cd9660_vget_internal(mp, ino, LK_EXCLUSIVE, vpp, imp->iso_ftype == ISO_FTYPE_RRIP, dp)); } @@ -644,7 +644,7 @@ cd9660_fhtovp(mp, fhp, vpp) ifhp->ifid_ino, ifhp->ifid_start); #endif - if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) { + if ((error = VFS_VGET(mp, ifhp->ifid_ino, LK_EXCLUSIVE, &nvp)) != 0) { *vpp = NULLVP; return (error); } @@ -659,9 +659,10 @@ cd9660_fhtovp(mp, fhp, vpp) } int -cd9660_vget(mp, ino, vpp) +cd9660_vget(mp, ino, flags, vpp) struct mount *mp; ino_t ino; + int flags; struct vnode **vpp; { @@ -671,7 +672,7 @@ cd9660_vget(mp, ino, vpp) * and force the extra read, but I don't want to think about fixing * that right now. */ - return (cd9660_vget_internal(mp, ino, vpp, + return (cd9660_vget_internal(mp, ino, flags, vpp, #if 0 VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP, #else @@ -681,9 +682,10 @@ cd9660_vget(mp, ino, vpp) } int -cd9660_vget_internal(mp, ino, vpp, relocated, isodir) +cd9660_vget_internal(mp, ino, flags, vpp, relocated, isodir) struct mount *mp; ino_t ino; + int flags; struct vnode **vpp; int relocated; struct iso_directory_record *isodir; @@ -697,7 +699,9 @@ cd9660_vget_internal(mp, ino, vpp, relocated, isodir) imp = VFSTOISOFS(mp); dev = imp->im_dev; - if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP) + if ((error = cd9660_ihashget(dev, ino, flags, vpp)) != 0) + return (error); + if (*vpp != NULL) return (0); /* Allocate a new vnode/iso_node. */ @@ -718,6 +722,18 @@ cd9660_vget_internal(mp, ino, vpp, relocated, isodir) ip->i_number = ino; /* + * Check to be sure that it did not show up. We have to put it + * on the hash chain as the cleanup from vput expects to find + * it there. + */ + if ((error = cd9660_ihashget(dev, ino, flags, vpp)) != 0 || + *vpp != NULL) { + cd9660_ihashins(ip); + vput(vp); + return (error); + } + + /* * Put it onto its hash chain and lock it so that other requests for * this inode will block if they arrive while we are sleeping waiting * for old data structures to be purged or for the contents of the diff --git a/sys/isofs/cd9660/iso.h b/sys/isofs/cd9660/iso.h index b62c723..453423a 100644 --- a/sys/isofs/cd9660/iso.h +++ b/sys/isofs/cd9660/iso.h @@ -254,7 +254,7 @@ struct iso_mnt { #define lblkno(imp, loc) ((loc) >> (imp)->im_bshift) #define blksize(imp, ip, lbn) ((imp)->logical_block_size) -int cd9660_vget_internal __P((struct mount *, ino_t, struct vnode **, int, +int cd9660_vget_internal __P((struct mount *, ino_t, int, struct vnode **, int, struct iso_directory_record *)); int cd9660_init __P((struct vfsconf *)); int cd9660_uninit __P((struct vfsconf *)); |