[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
vfs 2
- To: bugs_(_at_)_openbsd_(_dot_)_org
- Subject: vfs 2
- From: Ted Unangst <tedu_(_at_)_Stanford_(_dot_)_EDU>
- Date: Sun, 29 Dec 2002 18:06:28 -0800 (PST)
This is patch2. Make all the filesystems under miscfs use PDIRUNLOCK
as well in their private lookup() functions. Only affects fs's under
miscfs.
diff -ruNX nodiff vfs1/miscfs/fdesc/fdesc_vnops.c vfs2/miscfs/fdesc/fdesc_vnops.c
--- vfs1/miscfs/fdesc/fdesc_vnops.c Wed Dec 25 09:12:08 2002
+++ vfs2/miscfs/fdesc/fdesc_vnops.c Wed Dec 25 09:43:26 2002
@@ -254,11 +254,9 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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
diff -ruNX nodiff vfs1/miscfs/kernfs/kernfs_vnops.c vfs2/miscfs/kernfs/kernfs_vnops.c
--- vfs1/miscfs/kernfs/kernfs_vnops.c Wed Dec 25 09:12:08 2002
+++ vfs2/miscfs/kernfs/kernfs_vnops.c Wed Dec 25 09:43:26 2002
@@ -487,15 +487,16 @@
struct proc *p = cnp->cn_proc;
struct kern_target *kt;
struct vnode *vp;
- int error;
+ int error, wantpunlock;
#ifdef KERNFS_DIAGNOSTIC
printf("kernfs_lookup(%p)\n", ap);
printf("kernfs_lookup(dp = %p, vpp = %p, cnp = %p)\n", dvp, vpp, ap->a_cnp);
printf("kernfs_lookup(%s)\n", pname);
#endif
- VOP_UNLOCK(dvp, 0, p);
+
*vpp = NULLVP;
+ cnp->cn_flags &= ~PDIRUNLOCK;
if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
return (EROFS);
@@ -503,14 +504,14 @@
if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
VREF(dvp);
- vn_lock(dvp, LK_SHARED | LK_RETRY, p);
return (0);
}
+ wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));
+
kt = kernfs_findtarget(pname, cnp->cn_namelen);
if (kt == NULL) {
/* not found */
- vn_lock(dvp, LK_SHARED | LK_RETRY, p);
return(cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
}
@@ -524,17 +525,25 @@
*vpp = vp;
if (vget(vp, LK_EXCLUSIVE, p))
goto loop;
+ if (wantpunlock) {
+ VOP_UNLOCK(dvp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
return(0);
}
if ((error = kernfs_allocvp(kt, dvp->v_mount, vpp)) != 0) {
- vn_lock(dvp, LK_SHARED | LK_RETRY, p);
return(error);
}
vn_lock(*vpp, LK_SHARED | LK_RETRY, p);
- return(error);
+
+ if (wantpunlock) {
+ VOP_UNLOCK(dvp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
+ return (0);
}
/*ARGSUSED*/
diff -ruNX nodiff vfs1/miscfs/portal/portal_vnops.c vfs2/miscfs/portal/portal_vnops.c
--- vfs1/miscfs/portal/portal_vnops.c Wed Dec 25 09:12:08 2002
+++ vfs2/miscfs/portal/portal_vnops.c Wed Dec 25 09:43:26 2002
@@ -187,6 +187,7 @@
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
char *pname = cnp->cn_nameptr;
+ struct proc *p = cnp->cn_proc;
struct portalnode *pt;
int error;
struct vnode *fvp = 0;
@@ -201,7 +202,6 @@
if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
VREF(dvp);
- /*VOP_LOCK(dvp);*/
return (0);
}
@@ -228,7 +228,15 @@
pt->pt_fileid = portal_fileid++;
*vpp = fvp;
- /*VOP_LOCK(fvp);*/
+ VOP_LOCK(fvp, LK_EXCLUSIVE, p);
+ /*
+ * As we are the last component of the path name, fix up
+ * the locking on the directory node.
+ */
+ if ((cnp->cn_flags & LOCKPARENT) == 0) {
+ VOP_UNLOCK(dvp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
return (0);
bad:;
diff -ruNX nodiff vfs1/miscfs/procfs/procfs_vnops.c vfs2/miscfs/procfs/procfs_vnops.c
--- vfs1/miscfs/procfs/procfs_vnops.c Wed Dec 25 09:12:08 2002
+++ vfs2/miscfs/procfs/procfs_vnops.c Wed Dec 25 09:43:26 2002
@@ -751,9 +751,10 @@
pid_t pid;
struct pfsnode *pfs;
struct proc *p = NULL;
- int i, error, iscurproc = 0, isself = 0;
+ int i, error, wantpunlock, iscurproc = 0, isself = 0;
*vpp = NULL;
+ cnp->cn_flags &= ~PDIRUNLOCK;
if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
return (EROFS);
@@ -761,10 +762,10 @@
if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
VREF(dvp);
- /*VOP_LOCK(dvp);*/
return (0);
}
+ wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));
pfs = VTOPFS(dvp);
switch (pfs->pfs_type) {
case Proot:
@@ -777,12 +778,10 @@
if (iscurproc || isself) {
error = procfs_allocvp(dvp->v_mount, vpp, 0,
iscurproc ? Pcurproc : Pself);
-#if 0
if ((error == 0) && (wantpunlock)) {
- VOP_UNLOCK(dvp, 0);
+ VOP_UNLOCK(dvp, 0, curp);
cnp->cn_flags |= PDIRUNLOCK;
}
-#endif
return (error);
}
@@ -798,12 +797,10 @@
if (i != nproc_root_targets) {
error = procfs_allocvp(dvp->v_mount, vpp, 0,
pt->pt_pfstype);
-#if 0
if ((error == 0) && (wantpunlock)) {
- VOP_UNLOCK(dvp, 0);
+ VOP_UNLOCK(dvp, 0, curp);
cnp->cn_flags |= PDIRUNLOCK;
}
-#endif
return (error);
}
@@ -815,11 +812,29 @@
if (p == 0)
break;
- return (procfs_allocvp(dvp->v_mount, vpp, pid, Pproc));
+ error = procfs_allocvp(dvp->v_mount, vpp, pid, Pproc);
+ if ((error == 0) && wantpunlock) {
+ VOP_UNLOCK(dvp, 0, curp);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
+ return (error);
case Pproc:
- if (cnp->cn_flags & ISDOTDOT)
- return (procfs_root(dvp->v_mount, vpp));
+ /*
+ * do the .. dance. We unlock the directory, and then
+ * get the root dir. That will automatically return ..
+ * locked. Then if the caller wanted dvp locked, we
+ * re-lock.
+ */
+ if (cnp->cn_flags & ISDOTDOT) {
+ VOP_UNLOCK(dvp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ error = procfs_root(dvp->v_mount, vpp);
+ if ((error == 0) && (wantpunlock == 0) &&
+ ((error = vn_lock(dvp, LK_EXCLUSIVE, curp)) == 0))
+ cnp->cn_flags &= ~PDIRUNLOCK;
+ return (error);
+ }
p = pfind(pfs->pfs_pid);
if (p == 0)
@@ -840,12 +855,21 @@
/* We already checked that it exists. */
VREF(fvp);
vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, curp);
+ if (wantpunlock) {
+ VOP_UNLOCK(dvp, 0, curp);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
*vpp = fvp;
return (0);
}
- return (procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
- pt->pt_pfstype));
+ error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
+ pt->pt_pfstype);
+ if ((error == 0) && (wantpunlock)) {
+ VOP_UNLOCK(dvp, 0, curp);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
+ return (error);
default:
return (ENOTDIR);
--
"I promise you a police car on every sidewalk."
- M. Barry, Mayor of Washington, DC
Visit your host, monkey.org