summaryrefslogtreecommitdiffstats
path: root/sys/isofs/cd9660
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2002-03-17 01:25:47 +0000
committermckusick <mckusick@FreeBSD.org>2002-03-17 01:25:47 +0000
commit14dd08fd153468502c32dc2d9c1e25a6c2d761d1 (patch)
treeee06559e7b5061e6fc6cf074dfca793dd31c681b /sys/isofs/cd9660
parent34dcf8975d103d034d7e8b6788c0645cc93af254 (diff)
downloadFreeBSD-src-14dd08fd153468502c32dc2d9c1e25a6c2d761d1.zip
FreeBSD-src-14dd08fd153468502c32dc2d9c1e25a6c2d761d1.tar.gz
Add a flags parameter to VFS_VGET to pass through the desired
locking flags when acquiring a vnode. The immediate purpose is to allow polling lock requests (LK_NOWAIT) needed by soft updates to avoid deadlock when enlisting other processes to help with the background cleanup. For the future it will allow the use of shared locks for read access to vnodes. This change touches a lot of files as it affects most filesystems within the system. It has been well tested on FFS, loopback, and CD-ROM filesystems. only lightly on the others, so if you find a problem there, please let me (mckusick@mckusick.com) know.
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