summaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--sys/coda/coda_vnops.c2
-rw-r--r--sys/fs/cd9660/cd9660_lookup.c6
-rw-r--r--sys/fs/cd9660/cd9660_node.c18
-rw-r--r--sys/fs/cd9660/cd9660_node.h2
-rw-r--r--sys/fs/cd9660/cd9660_vfsops.c30
-rw-r--r--sys/fs/cd9660/iso.h2
-rw-r--r--sys/fs/coda/coda_vnops.c2
-rw-r--r--sys/fs/hpfs/hpfs.h2
-rw-r--r--sys/fs/hpfs/hpfs_hash.c18
-rw-r--r--sys/fs/hpfs/hpfs_subr.c5
-rw-r--r--sys/fs/hpfs/hpfs_vfsops.c18
-rw-r--r--sys/fs/hpfs/hpfs_vnops.c26
-rw-r--r--sys/fs/ntfs/ntfs_subr.c2
-rw-r--r--sys/fs/ntfs/ntfs_vfsops.c16
-rw-r--r--sys/fs/ntfs/ntfs_vnops.c4
-rw-r--r--sys/fs/nullfs/null_vfsops.c8
-rw-r--r--sys/fs/smbfs/smbfs_vfsops.c6
-rw-r--r--sys/fs/umapfs/umap_vfsops.c7
-rw-r--r--sys/gnu/ext2fs/ext2_alloc.c2
-rw-r--r--sys/gnu/ext2fs/ext2_ihash.c18
-rw-r--r--sys/gnu/ext2fs/ext2_lookup.c15
-rw-r--r--sys/gnu/ext2fs/ext2_vfsops.c9
-rw-r--r--sys/gnu/ext2fs/ext2_vnops.c2
-rw-r--r--sys/gnu/fs/ext2fs/ext2_alloc.c2
-rw-r--r--sys/gnu/fs/ext2fs/ext2_lookup.c15
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vfsops.c9
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vnops.c2
-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
-rw-r--r--sys/kern/vfs_default.c3
-rw-r--r--sys/nfsserver/nfs_serv.c6
-rw-r--r--sys/sys/mount.h7
-rw-r--r--sys/ufs/ffs/ffs_alloc.c6
-rw-r--r--sys/ufs/ffs/ffs_extern.h2
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c3
-rw-r--r--sys/ufs/ffs/ffs_softdep.c67
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c9
-rw-r--r--sys/ufs/ffs/softdep.h1
-rw-r--r--sys/ufs/ifs/ifs_lookup.c2
-rw-r--r--sys/ufs/ifs/ifs_vfsops.c10
-rw-r--r--sys/ufs/ufs/ufs_extern.h3
-rw-r--r--sys/ufs/ufs/ufs_ihash.c18
-rw-r--r--sys/ufs/ufs/ufs_lookup.c50
-rw-r--r--sys/ufs/ufs/ufs_vfsops.c4
-rw-r--r--sys/ufs/ufs/ufs_vnops.c2
48 files changed, 308 insertions, 191 deletions
diff --git a/sys/coda/coda_vnops.c b/sys/coda/coda_vnops.c
index 646ee34..c47d309 100644
--- a/sys/coda/coda_vnops.c
+++ b/sys/coda/coda_vnops.c
@@ -1854,7 +1854,7 @@ coda_grab_vnode(dev_t dev, ino_t ino, struct vnode **vpp)
}
/* XXX - ensure that nonzero-return means failure */
- error = VFS_VGET(mp,ino,vpp);
+ error = VFS_VGET(mp,ino,LK_EXCLUSIVE,vpp);
if (error) {
myprintf(("coda_grab_vnode: iget/vget(%lx, %lu) returns %p, err %d\n",
(u_long)dev2udev(dev), (u_long)ino, (void *)*vpp, error));
diff --git a/sys/fs/cd9660/cd9660_lookup.c b/sys/fs/cd9660/cd9660_lookup.c
index 706a7ae..da927e1 100644
--- a/sys/fs/cd9660/cd9660_lookup.c
+++ b/sys/fs/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/fs/cd9660/cd9660_node.c b/sys/fs/cd9660/cd9660_node.c
index 53ffeca..0060364 100644
--- a/sys/fs/cd9660/cd9660_node.c
+++ b/sys/fs/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/fs/cd9660/cd9660_node.h b/sys/fs/cd9660/cd9660_node.h
index 100c08e..2a0d7ef 100644
--- a/sys/fs/cd9660/cd9660_node.h
+++ b/sys/fs/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/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c
index 1e3719d..60a7b38 100644
--- a/sys/fs/cd9660/cd9660_vfsops.c
+++ b/sys/fs/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/fs/cd9660/iso.h b/sys/fs/cd9660/iso.h
index b62c723..453423a 100644
--- a/sys/fs/cd9660/iso.h
+++ b/sys/fs/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 *));
diff --git a/sys/fs/coda/coda_vnops.c b/sys/fs/coda/coda_vnops.c
index 646ee34..c47d309 100644
--- a/sys/fs/coda/coda_vnops.c
+++ b/sys/fs/coda/coda_vnops.c
@@ -1854,7 +1854,7 @@ coda_grab_vnode(dev_t dev, ino_t ino, struct vnode **vpp)
}
/* XXX - ensure that nonzero-return means failure */
- error = VFS_VGET(mp,ino,vpp);
+ error = VFS_VGET(mp,ino,LK_EXCLUSIVE,vpp);
if (error) {
myprintf(("coda_grab_vnode: iget/vget(%lx, %lu) returns %p, err %d\n",
(u_long)dev2udev(dev), (u_long)ino, (void *)*vpp, error));
diff --git a/sys/fs/hpfs/hpfs.h b/sys/fs/hpfs/hpfs.h
index bd90ce4..ec2cfad 100644
--- a/sys/fs/hpfs/hpfs.h
+++ b/sys/fs/hpfs/hpfs.h
@@ -393,7 +393,7 @@ void hpfs_hphashinit __P((void));
void hpfs_hphashdestroy __P((void));
struct hpfsnode *hpfs_hphashlookup __P((dev_t, lsn_t));
struct hpfsnode *hpfs_hphashget __P((dev_t, lsn_t));
-struct vnode *hpfs_hphashvget __P((dev_t, lsn_t, struct thread *));
+int hpfs_hphashvget __P((dev_t, lsn_t, int, struct vnode **, struct thread *));
void hpfs_hphashins __P((register struct hpfsnode *));
void hpfs_hphashrem __P((register struct hpfsnode *));
extern struct lock hpfs_hphash_lock;
diff --git a/sys/fs/hpfs/hpfs_hash.c b/sys/fs/hpfs/hpfs_hash.c
index 1c6601a..0a04a9a 100644
--- a/sys/fs/hpfs/hpfs_hash.c
+++ b/sys/fs/hpfs/hpfs_hash.c
@@ -122,15 +122,19 @@ loop:
}
#endif
-struct vnode *
-hpfs_hphashvget(dev, ino, td)
+int
+hpfs_hphashvget(dev, ino, flags, vpp, td)
dev_t dev;
lsn_t ino;
+ int flags;
+ struct vnode **vpp;
struct thread *td;
{
struct hpfsnode *hp;
struct vnode *vp;
+ int error;
+ *vpp = NULLVP;
loop:
mtx_lock(&hpfs_hphash_mtx);
LIST_FOREACH(hp, HPNOHASH(dev, ino), h_hash) {
@@ -138,13 +142,17 @@ loop:
vp = HPTOV(hp);
mtx_lock(&vp->v_interlock);
mtx_unlock(&hpfs_hphash_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(&hpfs_hphash_mtx);
- return (NULLVP);
+ return (0);
}
/*
diff --git a/sys/fs/hpfs/hpfs_subr.c b/sys/fs/hpfs/hpfs_subr.c
index 5fa32a5..b45ebbd 100644
--- a/sys/fs/hpfs/hpfs_subr.c
+++ b/sys/fs/hpfs/hpfs_subr.c
@@ -536,7 +536,8 @@ hpfs_validateparent (
if (hp->h_no == hp->h_fn.fn_parent) {
dhp = hp;
} else {
- error = VFS_VGET(hpmp->hpm_mp, hp->h_fn.fn_parent, &dvp);
+ error = VFS_VGET(hpmp->hpm_mp, hp->h_fn.fn_parent,
+ LK_EXCLUSIVE, &dvp);
if (error)
return (error);
dhp = VTOHP(dvp);
@@ -689,7 +690,7 @@ hpfs_updateparent (
dhp = hp;
} else {
error = VFS_VGET(hp->h_hpmp->hpm_mp, hp->h_fn.fn_parent,
- &dvp);
+ LK_EXCLUSIVE, &dvp);
if (error)
return (error);
dhp = VTOHP(dvp);
diff --git a/sys/fs/hpfs/hpfs_vfsops.c b/sys/fs/hpfs/hpfs_vfsops.c
index dcb5995..cf3c114 100644
--- a/sys/fs/hpfs/hpfs_vfsops.c
+++ b/sys/fs/hpfs/hpfs_vfsops.c
@@ -59,7 +59,7 @@ static int hpfs_root __P((struct mount *, struct vnode **));
static int hpfs_statfs __P((struct mount *, struct statfs *,
struct thread *));
static int hpfs_unmount __P((struct mount *, int, struct thread *));
-static int hpfs_vget __P((struct mount *mp, ino_t ino,
+static int hpfs_vget __P((struct mount *mp, ino_t ino, int flags,
struct vnode **vpp));
static int hpfs_mountfs __P((register struct vnode *, struct mount *,
struct hpfs_args *, struct thread *));
@@ -380,7 +380,7 @@ hpfs_root(
struct hpfsmount *hpmp = VFSTOHPFS(mp);
dprintf(("hpfs_root():\n"));
- error = VFS_VGET(mp, (ino_t)hpmp->hpm_su.su_rootfno, vpp);
+ error = VFS_VGET(mp, (ino_t)hpmp->hpm_su.su_rootfno, LK_EXCLUSIVE, vpp);
if(error) {
printf("hpfs_root: VFS_VGET failed: %d\n",error);
return (error);
@@ -429,7 +429,7 @@ hpfs_fhtovp(
struct hpfid *hpfhp = (struct hpfid *)fhp;
int error;
- if ((error = VFS_VGET(mp, hpfhp->hpfid_ino, &nvp)) != 0) {
+ if ((error = VFS_VGET(mp, hpfhp->hpfid_ino, LK_EXCLUSIVE, &nvp)) != 0) {
*vpp = NULLVP;
return (error);
}
@@ -460,6 +460,7 @@ static int
hpfs_vget(
struct mount *mp,
ino_t ino,
+ int flags,
struct vnode **vpp)
{
struct hpfsmount *hpmp = VFSTOHPFS(mp);
@@ -475,7 +476,9 @@ hpfs_vget(
hp = NULL;
vp = NULL;
- if ((*vpp = hpfs_hphashvget(hpmp->hpm_dev, ino, td)) != NULL) {
+ if ((error = hpfs_hphashvget(hpmp->hpm_dev, ino, flags, vpp, td)) != 0)
+ return (error);
+ if (*vpp != NULL) {
dprintf(("hashed\n"));
return (0);
}
@@ -531,7 +534,12 @@ hpfs_vget(
}
do {
- if ((*vpp = hpfs_hphashvget(hpmp->hpm_dev, ino, td)) != NULL) {
+ if ((error =
+ hpfs_hphashvget(hpmp->hpm_dev, ino, flags, vpp, td))) {
+ vput(vp);
+ return (error);
+ }
+ if (*vpp != NULL) {
dprintf(("hashed2\n"));
vput(vp);
return (0);
diff --git a/sys/fs/hpfs/hpfs_vnops.c b/sys/fs/hpfs/hpfs_vnops.c
index e3ed555..7b4d731 100644
--- a/sys/fs/hpfs/hpfs_vnops.c
+++ b/sys/fs/hpfs/hpfs_vnops.c
@@ -1096,21 +1096,18 @@ hpfs_lookup(ap)
dprintf(("hpfs_lookup(0x%x,...): .. faked (0x%x)\n",
dhp->h_no, dhp->h_fn.fn_parent));
- VOP_UNLOCK(dvp,0,cnp->cn_thread);
-
- error = VFS_VGET(hpmp->hpm_mp,
- dhp->h_fn.fn_parent, ap->a_vpp);
- if(error) {
+ if (VFS_VGET(hpmp->hpm_mp, dhp->h_fn.fn_parent,
+ LK_NOWAIT | LK_EXCLUSIVE, ap->a_vpp)) {
+ VOP_UNLOCK(dvp,0,cnp->cn_thread);
+ error = VFS_VGET(hpmp->hpm_mp,
+ dhp->h_fn.fn_parent, LK_EXCLUSIVE, ap->a_vpp);
VOP_LOCK(dvp, 0, cnp->cn_thread);
- return(error);
- }
-
- if( lockparent && (flags & ISLASTCN) &&
- (error = VOP_LOCK(dvp, 0, cnp->cn_thread)) ) {
- vput( *(ap->a_vpp) );
- return (error);
+ if(error)
+ return(error);
}
- return (error);
+ if (!lockparent || !(flags & ISLASTCN))
+ VOP_UNLOCK(dvp,0,cnp->cn_thread);
+ return (0);
} else {
struct buf *bp;
struct hpfsdirent *dep;
@@ -1148,7 +1145,8 @@ hpfs_lookup(ap)
return (0);
}
- error = VFS_VGET(hpmp->hpm_mp, dep->de_fnode, ap->a_vpp);
+ error = VFS_VGET(hpmp->hpm_mp, dep->de_fnode, LK_EXCLUSIVE,
+ ap->a_vpp);
if (error) {
printf("hpfs_lookup: VFS_VGET FAILED %d\n", error);
brelse(bp);
diff --git a/sys/fs/ntfs/ntfs_subr.c b/sys/fs/ntfs/ntfs_subr.c
index f14d741..de239f0 100644
--- a/sys/fs/ntfs/ntfs_subr.c
+++ b/sys/fs/ntfs/ntfs_subr.c
@@ -1946,7 +1946,7 @@ ntfs_toupper_use(mp, ntmp)
MALLOC(ntfs_toupper_tab, wchar *, 65536 * sizeof(wchar),
M_NTFSRDATA, M_WAITOK);
- if ((error = VFS_VGET(mp, NTFS_UPCASEINO, &vp)))
+ if ((error = VFS_VGET(mp, NTFS_UPCASEINO, LK_EXCLUSIVE, &vp)))
goto out;
error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
0, 65536*sizeof(wchar), (char *) ntfs_toupper_tab, NULL);
diff --git a/sys/fs/ntfs/ntfs_vfsops.c b/sys/fs/ntfs/ntfs_vfsops.c
index 712d4d3..48bacbe 100644
--- a/sys/fs/ntfs/ntfs_vfsops.c
+++ b/sys/fs/ntfs/ntfs_vfsops.c
@@ -68,7 +68,7 @@ static int ntfs_root __P((struct mount *, struct vnode **));
static int ntfs_statfs __P((struct mount *, struct statfs *,
struct thread *));
static int ntfs_unmount __P((struct mount *, int, struct thread *));
-static int ntfs_vget __P((struct mount *mp, ino_t ino,
+static int ntfs_vget __P((struct mount *mp, ino_t ino, int lkflags,
struct vnode **vpp));
static int ntfs_mountfs __P((register struct vnode *, struct mount *,
struct ntfs_args *, struct thread *));
@@ -367,7 +367,8 @@ ntfs_mountfs(devvp, mp, argsp, td)
{
int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO };
for (i=0; i<3; i++) {
- error = VFS_VGET(mp, pi[i], &(ntmp->ntm_sysvn[pi[i]]));
+ error = VFS_VGET(mp, pi[i], LK_EXCLUSIVE,
+ &(ntmp->ntm_sysvn[pi[i]]));
if(error)
goto out1;
ntmp->ntm_sysvn[pi[i]]->v_flag |= VSYSTEM;
@@ -397,7 +398,7 @@ ntfs_mountfs(devvp, mp, argsp, td)
struct attrdef ad;
/* Open $AttrDef */
- error = VFS_VGET(mp, NTFS_ATTRDEFINO, &vp );
+ error = VFS_VGET(mp, NTFS_ATTRDEFINO, LK_EXCLUSIVE, &vp );
if(error)
goto out1;
@@ -537,7 +538,7 @@ ntfs_root(
dprintf(("ntfs_root(): sysvn: %p\n",
VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO]));
- error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, &nvp);
+ error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, LK_EXCLUSIVE, &nvp);
if(error) {
printf("ntfs_root: VFS_VGET failed: %d\n",error);
return (error);
@@ -625,7 +626,7 @@ ntfs_fhtovp(
ddprintf(("ntfs_fhtovp(): %d\n", ntfhp->ntfid_ino));
- if ((error = VFS_VGET(mp, ntfhp->ntfid_ino, &nvp)) != 0) {
+ if ((error = VFS_VGET(mp, ntfhp->ntfid_ino, LK_EXCLUSIVE, &nvp)) != 0) {
*vpp = NULLVP;
return (error);
}
@@ -768,10 +769,11 @@ static int
ntfs_vget(
struct mount *mp,
ino_t ino,
+ int lkflags,
struct vnode **vpp)
{
- return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL,
- LK_EXCLUSIVE | LK_RETRY, 0, curthread, vpp);
+ return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL, lkflags, 0,
+ curthread, vpp);
}
static struct vfsops ntfs_vfsops = {
diff --git a/sys/fs/ntfs/ntfs_vnops.c b/sys/fs/ntfs/ntfs_vnops.c
index e07914b..31b910b 100644
--- a/sys/fs/ntfs/ntfs_vnops.c
+++ b/sys/fs/ntfs/ntfs_vnops.c
@@ -629,8 +629,8 @@ ntfs_lookup(ap)
dprintf(("ntfs_lookup: parentdir: %d\n",
vap->va_a_name->n_pnumber));
- error = VFS_VGET(ntmp->ntm_mountp,
- vap->va_a_name->n_pnumber,ap->a_vpp);
+ error = VFS_VGET(ntmp->ntm_mountp, vap->va_a_name->n_pnumber,
+ LK_EXCLUSIVE, ap->a_vpp);
ntfs_ntvattrrele(vap);
if (error) {
if (vn_lock(dvp,LK_EXCLUSIVE|LK_RETRY,cnp->cn_thread)==0)
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index 1ab0aaa..d0a1ed1 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -73,7 +73,8 @@ static int nullfs_statfs(struct mount *mp, struct statfs *sbp,
static int nullfs_sync(struct mount *mp, int waitfor,
struct ucred *cred, struct thread *td);
static int nullfs_unmount(struct mount *mp, int mntflags, struct thread *td);
-static int nullfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp);
+static int nullfs_vget(struct mount *mp, ino_t ino, int flags,
+ struct vnode **vpp);
static int nullfs_vptofh(struct vnode *vp, struct fid *fhp);
static int nullfs_extattrctl(struct mount *mp, int cmd,
struct vnode *filename_vp,
@@ -344,13 +345,14 @@ nullfs_sync(mp, waitfor, cred, td)
}
static int
-nullfs_vget(mp, ino, vpp)
+nullfs_vget(mp, ino, flags, vpp)
struct mount *mp;
ino_t ino;
+ int flags;
struct vnode **vpp;
{
int error;
- error = VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, vpp);
+ error = VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, flags, vpp);
if (error)
return (error);
diff --git a/sys/fs/smbfs/smbfs_vfsops.c b/sys/fs/smbfs/smbfs_vfsops.c
index b3b5cd3..575585c 100644
--- a/sys/fs/smbfs/smbfs_vfsops.c
+++ b/sys/fs/smbfs/smbfs_vfsops.c
@@ -90,7 +90,8 @@ static int smbfs_init(struct vfsconf *vfsp);
static int smbfs_uninit(struct vfsconf *vfsp);
#if __FreeBSD_version < 400009
-static int smbfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp);
+static int smbfs_vget(struct mount *mp, ino_t ino, int flags,
+ struct vnode **vpp);
static int smbfs_fhtovp(struct mount *, struct fid *,
struct sockaddr *, struct vnode **, int *,
struct ucred **);
@@ -467,9 +468,10 @@ loop:
* smbfs flat namespace lookup. Unsupported.
*/
/* ARGSUSED */
-static int smbfs_vget(mp, ino, vpp)
+static int smbfs_vget(mp, ino, flags, vpp)
struct mount *mp;
ino_t ino;
+ int flags;
struct vnode **vpp;
{
return (EOPNOTSUPP);
diff --git a/sys/fs/umapfs/umap_vfsops.c b/sys/fs/umapfs/umap_vfsops.c
index a22b8df..17bfdc1 100644
--- a/sys/fs/umapfs/umap_vfsops.c
+++ b/sys/fs/umapfs/umap_vfsops.c
@@ -73,7 +73,7 @@ static int umapfs_sync __P((struct mount *mp, int waitfor,
struct ucred *cred, struct thread *td));
static int umapfs_unmount __P((struct mount *mp, int mntflags,
struct thread *td));
-static int umapfs_vget __P((struct mount *mp, ino_t ino,
+static int umapfs_vget __P((struct mount *mp, ino_t ino, int flags,
struct vnode **vpp));
static int umapfs_vptofh __P((struct vnode *vp, struct fid *fhp));
static int umapfs_extattrctl __P((struct mount *mp, int cmd,
@@ -387,13 +387,14 @@ umapfs_sync(mp, waitfor, cred, td)
}
static int
-umapfs_vget(mp, ino, vpp)
+umapfs_vget(mp, ino, flags, vpp)
struct mount *mp;
ino_t ino;
+ int flags;
struct vnode **vpp;
{
- return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp));
+ return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, flags, vpp));
}
static int
diff --git a/sys/gnu/ext2fs/ext2_alloc.c b/sys/gnu/ext2fs/ext2_alloc.c
index 5b04196..f078e04 100644
--- a/sys/gnu/ext2fs/ext2_alloc.c
+++ b/sys/gnu/ext2fs/ext2_alloc.c
@@ -399,7 +399,7 @@ ext2_valloc(pvp, mode, cred, vpp)
if (ino == 0)
goto noinodes;
- error = VFS_VGET(pvp->v_mount, ino, vpp);
+ error = VFS_VGET(pvp->v_mount, ino, LK_EXCLUSIVE, vpp);
if (error) {
UFS_VFREE(pvp, ino, mode);
return (error);
diff --git a/sys/gnu/ext2fs/ext2_ihash.c b/sys/gnu/ext2fs/ext2_ihash.c
index d1537af..d31add3 100644
--- a/sys/gnu/ext2fs/ext2_ihash.c
+++ b/sys/gnu/ext2fs/ext2_ihash.c
@@ -93,15 +93,19 @@ ufs_ihashlookup(dev, inum)
* 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 *
-ufs_ihashget(dev, inum)
+int
+ufs_ihashget(dev, inum, flags, vpp)
dev_t dev;
ino_t inum;
+ int flags;
+ struct vnode **vpp;
{
struct thread *td = curthread; /* XXX */
struct inode *ip;
struct vnode *vp;
+ int error;
+ *vpp = NULL;
loop:
mtx_lock(&ufs_ihash_mtx);
LIST_FOREACH(ip, INOHASH(dev, inum), i_hash) {
@@ -109,13 +113,17 @@ loop:
vp = ITOV(ip);
mtx_lock(&vp->v_interlock);
mtx_unlock(&ufs_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(&ufs_ihash_mtx);
- return (NULL);
+ return (0);
}
/*
diff --git a/sys/gnu/ext2fs/ext2_lookup.c b/sys/gnu/ext2fs/ext2_lookup.c
index b2e1511..50479e0 100644
--- a/sys/gnu/ext2fs/ext2_lookup.c
+++ b/sys/gnu/ext2fs/ext2_lookup.c
@@ -601,7 +601,8 @@ found:
*vpp = vdp;
return (0);
}
- if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0)
+ if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE,
+ &tdp)) != 0)
return (error);
/*
* If directory is "sticky", then user must own
@@ -638,7 +639,8 @@ found:
*/
if (dp->i_number == dp->i_ino)
return (EISDIR);
- if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0)
+ if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE,
+ &tdp)) != 0)
return (error);
*vpp = tdp;
cnp->cn_flags |= SAVENAME;
@@ -669,7 +671,8 @@ found:
pdp = vdp;
if (flags & ISDOTDOT) {
VOP_UNLOCK(pdp, 0, td); /* race to get the inode */
- if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) {
+ if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE,
+ &tdp)) != 0) {
vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, td);
return (error);
}
@@ -683,7 +686,8 @@ found:
VREF(vdp); /* we want ourself, ie "." */
*vpp = vdp;
} else {
- if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0)
+ if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE,
+ &tdp)) != 0)
return (error);
if (!lockparent || !(flags & ISLASTCN))
VOP_UNLOCK(pdp, 0, td);
@@ -1064,7 +1068,8 @@ ext2_checkpath(source, target, cred)
if (dirbuf.dotdot_ino == rootino)
break;
vput(vp);
- if ((error = VFS_VGET(vp->v_mount, dirbuf.dotdot_ino, &vp)) != 0) {
+ if ((error = VFS_VGET(vp->v_mount, dirbuf.dotdot_ino,
+ LK_EXCLUSIVE, &vp)) != 0) {
vp = NULL;
break;
}
diff --git a/sys/gnu/ext2fs/ext2_vfsops.c b/sys/gnu/ext2fs/ext2_vfsops.c
index 15a94d9..8a7cc07 100644
--- a/sys/gnu/ext2fs/ext2_vfsops.c
+++ b/sys/gnu/ext2fs/ext2_vfsops.c
@@ -80,7 +80,7 @@ static int ext2_sbupdate __P((struct ufsmount *, int));
static int ext2_statfs __P((struct mount *, struct statfs *, struct thread *));
static int ext2_sync __P((struct mount *, int, struct ucred *, struct thread *));
static int ext2_unmount __P((struct mount *, int, struct thread *));
-static int ext2_vget __P((struct mount *, ino_t, struct vnode **));
+static int ext2_vget __P((struct mount *, ino_t, int, struct vnode **));
static int ext2_vptofh __P((struct vnode *, struct fid *));
static MALLOC_DEFINE(M_EXT2NODE, "EXT2 node", "EXT2 vnode private part");
@@ -982,9 +982,10 @@ loop:
* done by the calling routine.
*/
static int
-ext2_vget(mp, ino, vpp)
+ext2_vget(mp, ino, flags, vpp)
struct mount *mp;
ino_t ino;
+ int flags;
struct vnode **vpp;
{
register struct ext2_sb_info *fs;
@@ -999,7 +1000,9 @@ ext2_vget(mp, ino, vpp)
ump = VFSTOUFS(mp);
dev = ump->um_dev;
restart:
- if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
+ if ((error = ufs_ihashget(dev, ino, flags, vpp)) != 0)
+ return (error);
+ if (*vpp != NULL)
return (0);
/*
diff --git a/sys/gnu/ext2fs/ext2_vnops.c b/sys/gnu/ext2fs/ext2_vnops.c
index ad60728..a90c20f 100644
--- a/sys/gnu/ext2fs/ext2_vnops.c
+++ b/sys/gnu/ext2fs/ext2_vnops.c
@@ -285,7 +285,7 @@ ext2_mknod(ap)
(*vpp)->v_type = VNON;
ino = ip->i_number; /* Save this before vgone() invalidates ip. */
vgone(*vpp);
- error = VFS_VGET(ap->a_dvp->v_mount, ino, vpp);
+ error = VFS_VGET(ap->a_dvp->v_mount, ino, LK_EXCLUSIVE, vpp);
if (error) {
*vpp = NULL;
return (error);
diff --git a/sys/gnu/fs/ext2fs/ext2_alloc.c b/sys/gnu/fs/ext2fs/ext2_alloc.c
index 5b04196..f078e04 100644
--- a/sys/gnu/fs/ext2fs/ext2_alloc.c
+++ b/sys/gnu/fs/ext2fs/ext2_alloc.c
@@ -399,7 +399,7 @@ ext2_valloc(pvp, mode, cred, vpp)
if (ino == 0)
goto noinodes;
- error = VFS_VGET(pvp->v_mount, ino, vpp);
+ error = VFS_VGET(pvp->v_mount, ino, LK_EXCLUSIVE, vpp);
if (error) {
UFS_VFREE(pvp, ino, mode);
return (error);
diff --git a/sys/gnu/fs/ext2fs/ext2_lookup.c b/sys/gnu/fs/ext2fs/ext2_lookup.c
index b2e1511..50479e0 100644
--- a/sys/gnu/fs/ext2fs/ext2_lookup.c
+++ b/sys/gnu/fs/ext2fs/ext2_lookup.c
@@ -601,7 +601,8 @@ found:
*vpp = vdp;
return (0);
}
- if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0)
+ if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE,
+ &tdp)) != 0)
return (error);
/*
* If directory is "sticky", then user must own
@@ -638,7 +639,8 @@ found:
*/
if (dp->i_number == dp->i_ino)
return (EISDIR);
- if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0)
+ if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE,
+ &tdp)) != 0)
return (error);
*vpp = tdp;
cnp->cn_flags |= SAVENAME;
@@ -669,7 +671,8 @@ found:
pdp = vdp;
if (flags & ISDOTDOT) {
VOP_UNLOCK(pdp, 0, td); /* race to get the inode */
- if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) {
+ if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE,
+ &tdp)) != 0) {
vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, td);
return (error);
}
@@ -683,7 +686,8 @@ found:
VREF(vdp); /* we want ourself, ie "." */
*vpp = vdp;
} else {
- if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0)
+ if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE,
+ &tdp)) != 0)
return (error);
if (!lockparent || !(flags & ISLASTCN))
VOP_UNLOCK(pdp, 0, td);
@@ -1064,7 +1068,8 @@ ext2_checkpath(source, target, cred)
if (dirbuf.dotdot_ino == rootino)
break;
vput(vp);
- if ((error = VFS_VGET(vp->v_mount, dirbuf.dotdot_ino, &vp)) != 0) {
+ if ((error = VFS_VGET(vp->v_mount, dirbuf.dotdot_ino,
+ LK_EXCLUSIVE, &vp)) != 0) {
vp = NULL;
break;
}
diff --git a/sys/gnu/fs/ext2fs/ext2_vfsops.c b/sys/gnu/fs/ext2fs/ext2_vfsops.c
index 15a94d9..8a7cc07 100644
--- a/sys/gnu/fs/ext2fs/ext2_vfsops.c
+++ b/sys/gnu/fs/ext2fs/ext2_vfsops.c
@@ -80,7 +80,7 @@ static int ext2_sbupdate __P((struct ufsmount *, int));
static int ext2_statfs __P((struct mount *, struct statfs *, struct thread *));
static int ext2_sync __P((struct mount *, int, struct ucred *, struct thread *));
static int ext2_unmount __P((struct mount *, int, struct thread *));
-static int ext2_vget __P((struct mount *, ino_t, struct vnode **));
+static int ext2_vget __P((struct mount *, ino_t, int, struct vnode **));
static int ext2_vptofh __P((struct vnode *, struct fid *));
static MALLOC_DEFINE(M_EXT2NODE, "EXT2 node", "EXT2 vnode private part");
@@ -982,9 +982,10 @@ loop:
* done by the calling routine.
*/
static int
-ext2_vget(mp, ino, vpp)
+ext2_vget(mp, ino, flags, vpp)
struct mount *mp;
ino_t ino;
+ int flags;
struct vnode **vpp;
{
register struct ext2_sb_info *fs;
@@ -999,7 +1000,9 @@ ext2_vget(mp, ino, vpp)
ump = VFSTOUFS(mp);
dev = ump->um_dev;
restart:
- if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
+ if ((error = ufs_ihashget(dev, ino, flags, vpp)) != 0)
+ return (error);
+ if (*vpp != NULL)
return (0);
/*
diff --git a/sys/gnu/fs/ext2fs/ext2_vnops.c b/sys/gnu/fs/ext2fs/ext2_vnops.c
index ad60728..a90c20f 100644
--- a/sys/gnu/fs/ext2fs/ext2_vnops.c
+++ b/sys/gnu/fs/ext2fs/ext2_vnops.c
@@ -285,7 +285,7 @@ ext2_mknod(ap)
(*vpp)->v_type = VNON;
ino = ip->i_number; /* Save this before vgone() invalidates ip. */
vgone(*vpp);
- error = VFS_VGET(ap->a_dvp->v_mount, ino, vpp);
+ error = VFS_VGET(ap->a_dvp->v_mount, ino, LK_EXCLUSIVE, vpp);
if (error) {
*vpp = NULL;
return (error);
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 *));
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index dab13c2..9a3a3c1 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -802,9 +802,10 @@ vfs_stdsync (mp, waitfor, cred, td)
}
int
-vfs_stdvget (mp, ino, vpp)
+vfs_stdvget (mp, ino, flags, vpp)
struct mount *mp;
ino_t ino;
+ int flags;
struct vnode **vpp;
{
return (EOPNOTSUPP);
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
index 17aea87..2d79643 100644
--- a/sys/nfsserver/nfs_serv.c
+++ b/sys/nfsserver/nfs_serv.c
@@ -3428,7 +3428,8 @@ again:
* Probe one of the directory entries to see if the filesystem
* supports VGET.
*/
- if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp) == EOPNOTSUPP) {
+ if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, &nvp) ==
+ EOPNOTSUPP) {
error = NFSERR_NOTSUPP;
vrele(vp);
vp = NULL;
@@ -3462,7 +3463,8 @@ again:
* For readdir_and_lookup get the vnode using
* the file number.
*/
- if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp))
+ if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE,
+ &nvp))
goto invalid;
bzero((caddr_t)nfhp, NFSX_V3FH);
nfhp->fh_fsid =
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 5cd748d..505e034 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -358,7 +358,7 @@ struct vfsops {
struct thread *td));
int (*vfs_sync) __P((struct mount *mp, int waitfor,
struct ucred *cred, struct thread *td));
- int (*vfs_vget) __P((struct mount *mp, ino_t ino,
+ int (*vfs_vget) __P((struct mount *mp, ino_t ino, int flags,
struct vnode **vpp));
int (*vfs_fhtovp) __P((struct mount *mp, struct fid *fhp,
struct vnode **vpp));
@@ -381,7 +381,8 @@ struct vfsops {
#define VFS_QUOTACTL(MP,C,U,A,P) (*(MP)->mnt_op->vfs_quotactl)(MP, C, U, A, P)
#define VFS_STATFS(MP, SBP, P) (*(MP)->mnt_op->vfs_statfs)(MP, SBP, P)
#define VFS_SYNC(MP, WAIT, C, P) (*(MP)->mnt_op->vfs_sync)(MP, WAIT, C, P)
-#define VFS_VGET(MP, INO, VPP) (*(MP)->mnt_op->vfs_vget)(MP, INO, VPP)
+#define VFS_VGET(MP, INO, FLAGS, VPP) \
+ (*(MP)->mnt_op->vfs_vget)(MP, INO, FLAGS, VPP)
#define VFS_FHTOVP(MP, FIDP, VPP) \
(*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, VPP)
#define VFS_VPTOFH(VP, FIDP) (*(VP)->v_mount->mnt_op->vfs_vptofh)(VP, FIDP)
@@ -456,7 +457,7 @@ int vfs_stdquotactl __P((struct mount *mp, int cmds, uid_t uid,
int vfs_stdstatfs __P((struct mount *mp, struct statfs *sbp, struct thread *td));
int vfs_stdsync __P((struct mount *mp, int waitfor, struct ucred *cred,
struct thread *td));
-int vfs_stdvget __P((struct mount *mp, ino_t ino, struct vnode **vpp));
+int vfs_stdvget __P((struct mount *mp, ino_t ino, int, struct vnode **vpp));
int vfs_stdfhtovp __P((struct mount *mp, struct fid *fhp, struct vnode **vpp));
int vfs_stdcheckexp __P((struct mount *mp, struct sockaddr *nam,
int *extflagsp, struct ucred **credanonp));
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index 93e8c99..374c0b9 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -629,7 +629,7 @@ ffs_valloc(pvp, mode, cred, vpp)
(allocfcn_t *)ffs_nodealloccg);
if (ino == 0)
goto noinodes;
- error = VFS_VGET(pvp->v_mount, ino, vpp);
+ error = VFS_VGET(pvp->v_mount, ino, LK_EXCLUSIVE, vpp);
if (error) {
UFS_VFREE(pvp, ino, mode);
return (error);
@@ -1977,7 +1977,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
cmd.size);
}
#endif /* DEBUG */
- if ((error = VFS_VGET(mp, (ino_t)cmd.value, &vp)) != 0)
+ if ((error = VFS_VGET(mp, (ino_t)cmd.value, LK_EXCLUSIVE, &vp)))
break;
ip = VTOI(vp);
ip->i_nlink += cmd.size;
@@ -1996,7 +1996,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
cmd.size);
}
#endif /* DEBUG */
- if ((error = VFS_VGET(mp, (ino_t)cmd.value, &vp)) != 0)
+ if ((error = VFS_VGET(mp, (ino_t)cmd.value, LK_EXCLUSIVE, &vp)))
break;
ip = VTOI(vp);
ip->i_blocks += cmd.size;
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index cfcdcbd..1da7153 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -93,7 +93,7 @@ int ffs_update __P((struct vnode *, int));
int ffs_valloc __P((struct vnode *, int, struct ucred *, struct vnode **));
int ffs_vfree __P((struct vnode *, ino_t, int));
-int ffs_vget __P((struct mount *, ino_t, struct vnode **));
+int ffs_vget __P((struct mount *, ino_t, int, struct vnode **));
int ffs_vptofh __P((struct vnode *, struct fid *));
extern vop_t **ffs_vnodeop_p;
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index faca50f..a14fbea 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -1177,7 +1177,8 @@ ffs_snapshot_mount(mp)
for (snaploc = 0; snaploc < FSMAXSNAP; snaploc++) {
if (fs->fs_snapinum[snaploc] == 0)
return;
- if ((error = VFS_VGET(mp, fs->fs_snapinum[snaploc], &vp)) != 0){
+ if ((error = VFS_VGET(mp, fs->fs_snapinum[snaploc],
+ LK_EXCLUSIVE, &vp)) != 0){
printf("ffs_snapshot_mount: vget failed %d\n", error);
continue;
}
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 475ba17..5110b8c 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -165,7 +165,7 @@ static void initiate_write_filepage __P((struct pagedep *, struct buf *));
static void handle_written_mkdir __P((struct mkdir *, int));
static void initiate_write_inodeblock __P((struct inodedep *, struct buf *));
static void handle_workitem_freefile __P((struct freefile *));
-static void handle_workitem_remove __P((struct dirrem *));
+static void handle_workitem_remove __P((struct dirrem *, struct vnode *));
static struct dirrem *newdirrem __P((struct buf *, struct inode *,
struct inode *, int, struct dirrem **));
static void free_diradd __P((struct diradd *));
@@ -580,7 +580,7 @@ softdep_process_worklist(matchmnt)
struct mount *matchmnt;
{
struct thread *td = curthread;
- int matchcnt, loopcount;
+ int cnt, matchcnt, loopcount;
long starttime;
/*
@@ -618,7 +618,10 @@ softdep_process_worklist(matchmnt)
loopcount = 1;
starttime = time_second;
while (num_on_worklist > 0) {
- matchcnt += process_worklist_item(matchmnt, 0);
+ if ((cnt = process_worklist_item(matchmnt, 0)) == -1)
+ break;
+ else
+ matchcnt += cnt;
/*
* If a umount operation wants to run the worklist
@@ -675,7 +678,6 @@ process_worklist_item(matchmnt, flags)
int flags;
{
struct worklist *wk;
- struct dirrem *dirrem;
struct mount *mp;
struct vnode *vp;
int matchcnt = 0;
@@ -687,13 +689,19 @@ process_worklist_item(matchmnt, flags)
* inodes, we have to skip over any dirrem requests whose
* vnodes are resident and locked.
*/
+ vp = NULL;
LIST_FOREACH(wk, &softdep_workitem_pending, wk_list) {
+ if (wk->wk_state & INPROGRESS)
+ continue;
if ((flags & LK_NOWAIT) == 0 || wk->wk_type != D_DIRREM)
break;
- dirrem = WK_DIRREM(wk);
- vp = ufs_ihashlookup(VFSTOUFS(dirrem->dm_mnt)->um_dev,
- dirrem->dm_oldinum);
- if (vp == NULL || !VOP_ISLOCKED(vp, curthread))
+ wk->wk_state |= INPROGRESS;
+ FREE_LOCK(&lk);
+ VFS_VGET(WK_DIRREM(wk)->dm_mnt, WK_DIRREM(wk)->dm_oldinum,
+ LK_NOWAIT | LK_EXCLUSIVE, &vp);
+ ACQUIRE_LOCK(&lk);
+ wk->wk_state &= ~INPROGRESS;
+ if (vp != NULL)
break;
}
if (wk == 0) {
@@ -713,7 +721,7 @@ process_worklist_item(matchmnt, flags)
"process_worklist_item");
if (mp == matchmnt)
matchcnt += 1;
- handle_workitem_remove(WK_DIRREM(wk));
+ handle_workitem_remove(WK_DIRREM(wk), vp);
break;
case D_FREEBLKS:
@@ -2280,8 +2288,9 @@ handle_workitem_freeblocks(freeblks, flags)
* to see if the block count needs to be adjusted.
*/
if (freeblks->fb_chkcnt != blocksreleased &&
- (fs->fs_flags & FS_UNCLEAN) != 0 && (flags & LK_NOWAIT) == 0 &&
- VFS_VGET(freeblks->fb_mnt, freeblks->fb_previousinum, &vp) == 0) {
+ (fs->fs_flags & FS_UNCLEAN) != 0 &&
+ VFS_VGET(freeblks->fb_mnt, freeblks->fb_previousinum,
+ (flags & LK_NOWAIT) | LK_EXCLUSIVE, &vp) == 0) {
ip = VTOI(vp);
ip->i_blocks += freeblks->fb_chkcnt - blocksreleased;
ip->i_flag |= IN_CHANGE;
@@ -2742,7 +2751,7 @@ softdep_setup_remove(bp, dp, ip, isrmdir)
prevdirrem, dm_next);
dirrem->dm_dirinum = dirrem->dm_pagedep->pd_ino;
FREE_LOCK(&lk);
- handle_workitem_remove(dirrem);
+ handle_workitem_remove(dirrem, NULL);
}
}
@@ -3033,8 +3042,9 @@ softdep_releasefile(ip)
* If the link count reaches zero, the file is removed.
*/
static void
-handle_workitem_remove(dirrem)
+handle_workitem_remove(dirrem, xp)
struct dirrem *dirrem;
+ struct vnode *xp;
{
struct thread *td = curthread;
struct inodedep *inodedep;
@@ -3043,7 +3053,9 @@ handle_workitem_remove(dirrem)
ino_t oldinum;
int error;
- if ((error = VFS_VGET(dirrem->dm_mnt, dirrem->dm_oldinum, &vp)) != 0) {
+ if ((vp = xp) == NULL &&
+ (error = VFS_VGET(dirrem->dm_mnt, dirrem->dm_oldinum, LK_EXCLUSIVE,
+ &vp)) != 0) {
softdep_error("handle_workitem_remove: vget", error);
return;
}
@@ -3112,7 +3124,7 @@ handle_workitem_remove(dirrem)
check_inode_unwritten(inodedep)) {
FREE_LOCK(&lk);
vput(vp);
- handle_workitem_remove(dirrem);
+ handle_workitem_remove(dirrem, NULL);
return;
}
WORKLIST_INSERT(&inodedep->id_inowait, &dirrem->dm_list);
@@ -4228,16 +4240,19 @@ softdep_fsync(vp)
/*
* We prevent deadlock by always fetching inodes from the
* root, moving down the directory tree. Thus, when fetching
- * our parent directory, we must unlock ourselves before
- * requesting the lock on our parent. See the comment in
- * ufs_lookup for details on possible races.
+ * our parent directory, we first try to get the lock. If
+ * that fails, we must unlock ourselves before requesting
+ * the lock on our parent. See the comment in ufs_lookup
+ * for details on possible races.
*/
FREE_LOCK(&lk);
- VOP_UNLOCK(vp, 0, td);
- error = VFS_VGET(mnt, parentino, &pvp);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
- if (error != 0)
- return (error);
+ if (VFS_VGET(mnt, parentino, LK_NOWAIT | LK_EXCLUSIVE, &pvp)) {
+ VOP_UNLOCK(vp, 0, td);
+ error = VFS_VGET(mnt, parentino, LK_EXCLUSIVE, &pvp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+ if (error != 0)
+ return (error);
+ }
/*
* All MKDIR_PARENT dependencies and all the NEWBLOCK pagedeps
* that are contained in direct blocks will be resolved by
@@ -4735,7 +4750,7 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
inum = dap->da_newinum;
if (dap->da_state & MKDIR_BODY) {
FREE_LOCK(&lk);
- if ((error = VFS_VGET(mp, inum, &vp)) != 0)
+ if ((error = VFS_VGET(mp, inum, LK_EXCLUSIVE, &vp)))
break;
if ((error=VOP_FSYNC(vp, td->td_ucred, MNT_NOWAIT, td)) ||
(error=VOP_FSYNC(vp, td->td_ucred, MNT_NOWAIT, td))) {
@@ -4999,7 +5014,7 @@ clear_remove(td)
FREE_LOCK(&lk);
if (vn_start_write(NULL, &mp, V_NOWAIT) != 0)
continue;
- if ((error = VFS_VGET(mp, ino, &vp)) != 0) {
+ if ((error = VFS_VGET(mp, ino, LK_EXCLUSIVE, &vp))) {
softdep_error("clear_remove: vget", error);
vn_finished_write(mp);
return;
@@ -5072,7 +5087,7 @@ clear_inodedeps(td)
FREE_LOCK(&lk);
if (vn_start_write(NULL, &mp, V_NOWAIT) != 0)
continue;
- if ((error = VFS_VGET(mp, ino, &vp)) != 0) {
+ if ((error = VFS_VGET(mp, ino, LK_EXCLUSIVE, &vp)) != 0) {
softdep_error("clear_inodedeps: vget", error);
vn_finished_write(mp);
return;
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index ce4198c..025d30a 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -158,7 +158,6 @@ ffs_mount(mp, path, data, ndp, td)
if ((error = ffs_mountfs(rootvp, mp, td, M_FFSNODE)) != 0)
return (error);
-
(void)VFS_STATFS(mp, &mp->mnt_stat, td);
return (0);
}
@@ -1143,9 +1142,10 @@ static int ffs_inode_hash_lock;
static struct mtx ffs_inode_hash_mtx;
int
-ffs_vget(mp, ino, vpp)
+ffs_vget(mp, ino, flags, vpp)
struct mount *mp;
ino_t ino;
+ int flags;
struct vnode **vpp;
{
struct fs *fs;
@@ -1159,9 +1159,10 @@ ffs_vget(mp, ino, vpp)
ump = VFSTOUFS(mp);
dev = ump->um_dev;
restart:
- if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
+ if ((error = ufs_ihashget(dev, ino, flags, vpp)) != 0)
+ return (error);
+ if (*vpp != NULL)
return (0);
- }
/*
* Lock out the creation of new entries in the FFS hash table in
diff --git a/sys/ufs/ffs/softdep.h b/sys/ufs/ffs/softdep.h
index 5610bdc..cdb1f68 100644
--- a/sys/ufs/ffs/softdep.h
+++ b/sys/ufs/ffs/softdep.h
@@ -101,6 +101,7 @@
#define IOSTARTED 0x0200 /* inodedep & pagedep only */
#define SPACECOUNTED 0x0400 /* inodedep only */
#define NEWBLOCK 0x0800 /* pagedep only */
+#define INPROGRESS 0x1000 /* dirrem, freeblks, freefrag, freefile only */
#define ONWORKLIST 0x8000
#define ALLCOMPLETE (ATTACHED | COMPLETE | DEPCOMPLETE)
diff --git a/sys/ufs/ifs/ifs_lookup.c b/sys/ufs/ifs/ifs_lookup.c
index c6e5873..510b02b 100644
--- a/sys/ufs/ifs/ifs_lookup.c
+++ b/sys/ufs/ifs/ifs_lookup.c
@@ -242,7 +242,7 @@ ifs_lookup(ap)
return ENOENT;
}
/* Now, we can get the vnode */
- error = VFS_VGET(vdp->v_mount, (long)inodenum, &tdp);
+ error = VFS_VGET(vdp->v_mount, (long)inodenum, LK_EXCLUSIVE, &tdp);
if (error)
return (error);
if (!lockparent || !(flags & ISLASTCN))
diff --git a/sys/ufs/ifs/ifs_vfsops.c b/sys/ufs/ifs/ifs_vfsops.c
index 7eade14..b86048f 100644
--- a/sys/ufs/ifs/ifs_vfsops.c
+++ b/sys/ufs/ifs/ifs_vfsops.c
@@ -71,7 +71,7 @@ static MALLOC_DEFINE(M_IFSNODE, "IFS node", "IFS vnode private part");
static int ifs_init (struct vfsconf *);
static int ifs_mount (struct mount *, char *, caddr_t,
struct nameidata *, struct thread *);
-extern int ifs_vget (struct mount *, ino_t, struct vnode **);
+extern int ifs_vget (struct mount *, ino_t, int, struct vnode **);
@@ -151,9 +151,10 @@ ifs_init(vfsp)
}
int
-ifs_vget(mp, ino, vpp)
+ifs_vget(mp, ino, flags, vpp)
struct mount *mp;
ino_t ino;
+ int flags;
struct vnode **vpp;
{
struct fs *fs;
@@ -167,9 +168,10 @@ ifs_vget(mp, ino, vpp)
ump = VFSTOUFS(mp);
dev = ump->um_dev;
restart:
- if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
+ if ((error = ufs_ihashget(dev, ino, flags, vpp)) != 0)
+ return (error);
+ if (*vpp != NULL)
return (0);
- }
/*
* Lock out the creation of new entries in the FFS hash table in
diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h
index c4e2795..dc59164 100644
--- a/sys/ufs/ufs/ufs_extern.h
+++ b/sys/ufs/ufs/ufs_extern.h
@@ -74,8 +74,7 @@ int ufs_direnter __P((struct vnode *, struct vnode *, struct direct *,
int ufs_dirremove __P((struct vnode *, struct inode *, int, int));
int ufs_dirrewrite __P((struct inode *, struct inode *, ino_t, int, int));
int ufs_getlbns __P((struct vnode *, ufs_daddr_t, struct indir *, int *));
-struct vnode *
- ufs_ihashget __P((dev_t, ino_t));
+int ufs_ihashget __P((dev_t, ino_t, int, struct vnode **));
void ufs_ihashinit __P((void));
void ufs_ihashins __P((struct inode *));
struct vnode *
diff --git a/sys/ufs/ufs/ufs_ihash.c b/sys/ufs/ufs/ufs_ihash.c
index d1537af..d31add3 100644
--- a/sys/ufs/ufs/ufs_ihash.c
+++ b/sys/ufs/ufs/ufs_ihash.c
@@ -93,15 +93,19 @@ ufs_ihashlookup(dev, inum)
* 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 *
-ufs_ihashget(dev, inum)
+int
+ufs_ihashget(dev, inum, flags, vpp)
dev_t dev;
ino_t inum;
+ int flags;
+ struct vnode **vpp;
{
struct thread *td = curthread; /* XXX */
struct inode *ip;
struct vnode *vp;
+ int error;
+ *vpp = NULL;
loop:
mtx_lock(&ufs_ihash_mtx);
LIST_FOREACH(ip, INOHASH(dev, inum), i_hash) {
@@ -109,13 +113,17 @@ loop:
vp = ITOV(ip);
mtx_lock(&vp->v_interlock);
mtx_unlock(&ufs_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(&ufs_ihash_mtx);
- return (NULL);
+ return (0);
}
/*
diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
index bbb07af..a668a18 100644
--- a/sys/ufs/ufs/ufs_lookup.c
+++ b/sys/ufs/ufs/ufs_lookup.c
@@ -508,14 +508,8 @@ found:
*vpp = vdp;
return (0);
}
- if (flags & ISDOTDOT)
- VOP_UNLOCK(vdp, 0, td); /* race to get the inode */
- error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp);
- if (flags & ISDOTDOT) {
- if (vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, td) != 0)
- cnp->cn_flags |= PDIRUNLOCK;
- }
- if (error)
+ if ((error = VFS_VGET(vdp->v_mount, dp->i_ino,
+ LK_EXCLUSIVE, &tdp)) != 0)
return (error);
/*
* If directory is "sticky", then user must own
@@ -544,7 +538,7 @@ found:
* regular file, or empty directory.
*/
if (nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
- if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread)) != 0)
+ if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread)))
return (error);
/*
* Careful about locking second inode.
@@ -552,14 +546,8 @@ found:
*/
if (dp->i_number == dp->i_ino)
return (EISDIR);
- if (flags & ISDOTDOT)
- VOP_UNLOCK(vdp, 0, td); /* race to get the inode */
- error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp);
- if (flags & ISDOTDOT) {
- if (vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, td) != 0)
- cnp->cn_flags |= PDIRUNLOCK;
- }
- if (error)
+ if ((error = VFS_VGET(vdp->v_mount, dp->i_ino,
+ LK_EXCLUSIVE, &tdp)) != 0)
return (error);
*vpp = tdp;
cnp->cn_flags |= SAVENAME;
@@ -591,26 +579,25 @@ found:
*/
pdp = vdp;
if (flags & ISDOTDOT) {
- VOP_UNLOCK(pdp, 0, td); /* race to get the inode */
- cnp->cn_flags |= PDIRUNLOCK;
- if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) {
- if (vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, td) == 0)
- cnp->cn_flags &= ~PDIRUNLOCK;
- return (error);
- }
- if (lockparent && (flags & ISLASTCN)) {
- if ((error = vn_lock(pdp, LK_EXCLUSIVE, td)) != 0) {
- vput(tdp);
+ if ((VFS_VGET(pdp->v_mount, dp->i_ino, LK_NOWAIT | LK_EXCLUSIVE,
+ &tdp)) != 0) {
+ VOP_UNLOCK(pdp, 0, td); /* race to get the inode */
+ error = VFS_VGET(pdp->v_mount, dp->i_ino,
+ LK_EXCLUSIVE, &tdp);
+ vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, td);
+ if (error)
return (error);
- }
- cnp->cn_flags &= ~PDIRUNLOCK;
+ }
+ if (!lockparent || !(flags & ISLASTCN)) {
+ VOP_UNLOCK(pdp, 0, td);
+ cnp->cn_flags |= PDIRUNLOCK;
}
*vpp = tdp;
} else if (dp->i_number == dp->i_ino) {
VREF(vdp); /* we want ourself, ie "." */
*vpp = vdp;
} else {
- error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp);
+ error = VFS_VGET(pdp->v_mount, dp->i_ino, LK_EXCLUSIVE, &tdp);
if (error)
return (error);
if (!lockparent || !(flags & ISLASTCN)) {
@@ -1254,7 +1241,8 @@ ufs_checkpath(source, target, cred)
if (dirbuf.dotdot_ino == rootino)
break;
vput(vp);
- error = VFS_VGET(vp->v_mount, dirbuf.dotdot_ino, &vp);
+ error = VFS_VGET(vp->v_mount, dirbuf.dotdot_ino,
+ LK_EXCLUSIVE, &vp);
if (error) {
vp = NULL;
break;
diff --git a/sys/ufs/ufs/ufs_vfsops.c b/sys/ufs/ufs/ufs_vfsops.c
index e6cbd6c..c9176d9 100644
--- a/sys/ufs/ufs/ufs_vfsops.c
+++ b/sys/ufs/ufs/ufs_vfsops.c
@@ -84,7 +84,7 @@ ufs_root(mp, vpp)
struct vnode *nvp;
int error;
- error = VFS_VGET(mp, (ino_t)ROOTINO, &nvp);
+ error = VFS_VGET(mp, (ino_t)ROOTINO, LK_EXCLUSIVE, &nvp);
if (error)
return (error);
*vpp = nvp;
@@ -199,7 +199,7 @@ ufs_fhtovp(mp, ufhp, vpp)
struct vnode *nvp;
int error;
- error = VFS_VGET(mp, ufhp->ufid_ino, &nvp);
+ error = VFS_VGET(mp, ufhp->ufid_ino, LK_EXCLUSIVE, &nvp);
if (error) {
*vpp = NULLVP;
return (error);
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index bf05ff3..9dd3eab 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -244,7 +244,7 @@ ufs_mknod(ap)
(*vpp)->v_type = VNON;
ino = ip->i_number; /* Save this before vgone() invalidates ip. */
vgone(*vpp);
- error = VFS_VGET(ap->a_dvp->v_mount, ino, vpp);
+ error = VFS_VGET(ap->a_dvp->v_mount, ino, LK_EXCLUSIVE, vpp);
if (error) {
*vpp = NULL;
return (error);
OpenPOWER on IntegriCloud