diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2003-01-31 17:37:51 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2003-01-31 17:37:51 +0000 |
commit | 1b0b18abe62afb1a61733a6f5891a98bfbea81ec (patch) | |
tree | 29dc896fd65580ea85012ef60aaf813858629e3f /sys/miscfs/fdesc | |
parent | 2bccdd51809becfe909c271f5fef4d380c663209 (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.c | 46 |
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 |