[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

vfs 2



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