summaryrefslogtreecommitdiffstats
path: root/sys/isofs/cd9660
diff options
context:
space:
mode:
Diffstat (limited to 'sys/isofs/cd9660')
-rw-r--r--sys/isofs/cd9660/cd9660_lookup.c6
-rw-r--r--sys/isofs/cd9660/cd9660_node.c18
-rw-r--r--sys/isofs/cd9660/cd9660_node.h2
-rw-r--r--sys/isofs/cd9660/cd9660_vfsops.c30
-rw-r--r--sys/isofs/cd9660/iso.h2
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 *));
OpenPOWER on IntegriCloud