summaryrefslogtreecommitdiff
path: root/sys/miscfs/fdesc
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2003-01-31 17:37:51 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2003-01-31 17:37:51 +0000
commit1b0b18abe62afb1a61733a6f5891a98bfbea81ec (patch)
tree29dc896fd65580ea85012ef60aaf813858629e3f /sys/miscfs/fdesc
parent2bccdd51809becfe909c271f5fef4d380c663209 (diff)
File system locking fixups, mostly from NetBSD:
- cache_lookup move common code from various fs's here always return with vnode and parent locked adjust return codes - PDIRUNLOCK - new flag set if lookup couldn't lock parent vnode - kernfs and procfs lock vnode in get_root don't unlock (again) in kernfs_freevp fix memory leak in procfs From tedu@stanford.edu deraadt@ and various other ok
Diffstat (limited to 'sys/miscfs/fdesc')
-rw-r--r--sys/miscfs/fdesc/fdesc_vnops.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/sys/miscfs/fdesc/fdesc_vnops.c b/sys/miscfs/fdesc/fdesc_vnops.c
index c54cbe0a4e3..1e96dc206d3 100644
--- a/sys/miscfs/fdesc/fdesc_vnops.c
+++ b/sys/miscfs/fdesc/fdesc_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fdesc_vnops.c,v 1.32 2002/08/23 15:39:31 art Exp $ */
+/* $OpenBSD: fdesc_vnops.c,v 1.33 2003/01/31 17:37:50 art Exp $ */
/* $NetBSD: fdesc_vnops.c,v 1.32 1996/04/11 11:24:29 mrg Exp $ */
/*
@@ -254,11 +254,9 @@ fdesc_lookup(v)
struct vnode *fvp;
char *ln;
- VOP_UNLOCK(dvp, 0, p);
if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
VREF(dvp);
- vn_lock(dvp, LK_SHARED | LK_RETRY, p);
return (0);
}
@@ -277,8 +275,7 @@ fdesc_lookup(v)
goto bad;
*vpp = fvp;
fvp->v_type = VDIR;
- vn_lock(fvp, LK_SHARED | LK_RETRY, p);
- return (0);
+ goto good;
}
if (cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) {
@@ -292,8 +289,7 @@ fdesc_lookup(v)
goto bad;
*vpp = fvp;
fvp->v_type = VCHR;
- vn_lock(fvp, LK_SHARED | LK_RETRY, p);
- return (0);
+ goto good;
}
ln = 0;
@@ -323,8 +319,7 @@ fdesc_lookup(v)
VTOFDESC(fvp)->fd_link = ln;
*vpp = fvp;
fvp->v_type = VLNK;
- vn_lock(fvp, LK_SHARED | LK_RETRY, p);
- return (0);
+ goto good;
} else {
error = ENOENT;
goto bad;
@@ -334,10 +329,18 @@ fdesc_lookup(v)
case Fdevfd:
if (cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
- if ((error = fdesc_root(dvp->v_mount, vpp)))
+ VOP_UNLOCK(dvp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ error = fdesc_root(dvp->v_mount, vpp);
+ if (error)
goto bad;
-
- return (0);
+ /* If we're at the last component and need the
+ * parent locked, undo the unlock above.
+ */
+ if (((~cnp->cn_flags & (ISLASTCN | LOCKPARENT)) == 0) &&
+ ((error = vn_lock(dvp, LK_EXCLUSIVE, p)) == 0))
+ cnp->cn_flags &= ~PDIRUNLOCK;
+ return (error);
}
fd = 0;
@@ -361,15 +364,26 @@ fdesc_lookup(v)
if (error)
goto bad;
VTOFDESC(fvp)->fd_fd = fd;
- vn_lock(fvp, LK_SHARED | LK_RETRY, p);
*vpp = fvp;
- return (0);
+ goto good;
}
-bad:;
- vn_lock(dvp, LK_SHARED | LK_RETRY, p);
+bad:
*vpp = NULL;
return (error);
+
+good:
+ /*
+ * As "." was special cased above, we now unlock the parent if we're
+ * supposed to. We're only supposed to not unlock if this is the
+ * last component, and the caller requested LOCKPARENT. So if either
+ * condition is false, unlock.
+ */
+ if (((~cnp->cn_flags) & (ISLASTCN | LOCKPARENT)) != 0) {
+ VOP_UNLOCK(dvp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
+ return (0);
}
int