new panic (was: Re: "busy buffer problem" panics)

Matthew Dillon dillon at apollo.backplane.com
Wed Sep 8 16:36:56 PDT 2004


:
:Oops, sorry Matt, seem to have misplaced my leaf password ...
:here's a better traceback though - one with line numbers -
:
:...
:      tf_eax = -872183968, tf_trapno = 12, tf_err = 0, tf_eip = -1071869799, tf_cs = 8, tf_eflags = 66118, 
:      tf_esp = -1070839358, tf_ss = -714257964}) at ../../i386/i386/trap.c:613
:#6  0xc01c9099 in lwkt_reltoken (_ref=0xd56d49d4) at ../../kern/lwkt_token.c:408
:#7  0xc01f99f2 in vrele (vp=0xc02c49c2) at ../../kern/vfs_subr.c:1703
:#8  0xc03366e9 in linux_copyin_path (uname=0x80a0017 "/etc/ld.so.conf", kname=0xd56d4bac, flags=2)
:    at ../../emulation/linux/linux_util.c:119
:#9  0xc032e28d in linux_open (args=0xd56d4c38) at ../../emulation/linux/linux_file.c:101
:#10 0xc036368a in syscall2 (frame={tf_fs = 47, tf_es = 47, tf_ds = 47, tf_edi = 134951678, tf_esi = 8, 
:      tf_ebp = -1077937400, tf_isp = -714257036, tf_ebx = 134873111, tf_edx = 438, tf_ecx = 0, tf_eax = 5, 
:      tf_trapno = 12, tf_err = 2, tf_eip = 134601853, tf_cs = 31, tf_eflags = 582, tf_esp = -1077937496, 
:      tf_ss = 47}) at ../../i386/i386/trap.c:1350
:#11 0xc03553da in Xint0x80_syscall ()
:#12 0x8051316 in ?? ()
:#13 0x80499ba in ?? ()
:#14 0x80484c4 in ?? ()
:#15 0x804c1eb in ?? ()
:(kgdb) quit

    It can't be line 119 of linux_util.c, that's in the middle of a comment
    if you are using the patch I posted.  If you are not using the patch
    I posted then you need to try the patch.

    I've included it again below.  This one also contains some linprocfs
    fixes in addition to the original linux_util.c patch.  Make sure you
    are running a kernel with this patch and see if it panics... if it 
    does, get a another core dump and backtrace (and hopefully it won't list
    a line number that is in the middle of a comment).

					-Matt
					Matthew Dillon 
					<dillon at xxxxxxxxxxxxx>

Index: linux_util.c
===================================================================
RCS file: /cvs/src/sys/emulation/linux/linux_util.c,v
retrieving revision 1.8
diff -u -r1.8 linux_util.c
--- linux_util.c	13 Nov 2003 04:04:42 -0000	1.8
+++ linux_util.c	3 Sep 2004 04:49:27 -0000
@@ -74,10 +74,8 @@
 	length = strlen(linux_emul_path);
 	bcopy(linux_emul_path, buf, length);
 	error = copyinstr(uname, buf + length, MAXPATHLEN - length, &dummy);
-	if (error) {
-		linux_free_path(kname);
-		return (error);
-	}
+	if (error)
+		goto done;
 
 	switch (flags) {
 	case LINUX_PATH_CREATE:
@@ -87,14 +85,20 @@
 		 * the last '/'.
 		 */
 		cp = buf + strlen(buf);
-		while (*--cp != '/');
-		*cp = '\0';
+		while (--cp >= buf) {
+			if (*cp == '/')
+				break;
+		}
+		if (cp < buf)
+			goto dont_translate;
+		*cp = 0;
 
 		NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, buf, td);
 		error = namei(&nd);
 		if (error)
 			goto dont_translate;
-
+		NDFREE(&nd, NDF_ONLY_PNBUF);
+		vrele(nd.ni_vp);
 		*cp = '/';
 		return (0);
 	case LINUX_PATH_EXISTS:
@@ -119,30 +123,36 @@
 		NDINIT(&ndroot, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE,
 		    linux_emul_path, td);
 		error = namei(&ndroot);
-		if (error)
+		if (error) {
+			NDFREE(&nd, NDF_ONLY_PNBUF);
+			vrele(nd.ni_vp);
 			goto dont_translate;
+		}
 		
 		error = VOP_GETATTR(nd.ni_vp, &vat, td);
+		if (error == 0) {
+			error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td);
+			if (error == 0) {
+				if (vat.va_fsid == vatroot.va_fsid &&
+				    vat.va_fileid == vatroot.va_fileid)
+					error = ENOENT;
+			}
+		}
+		NDFREE(&nd, NDF_ONLY_PNBUF);
+		vrele(nd.ni_vp);
+		NDFREE(&ndroot, NDF_ONLY_PNBUF);
+		vrele(ndroot.ni_vp);
 		if (error)
 			goto dont_translate;
-
-		error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td);
-		if (error)
-			goto dont_translate;
-
-		if (vat.va_fsid == vatroot.va_fsid &&
-		    vat.va_fileid == vatroot.va_fileid)
-			goto dont_translate;
-
 		return (0);
 	default:
-		linux_free_path(kname);
-		return (EINVAL);
+		error = EINVAL;
+		goto done;
 	}
 	
 dont_translate:
-
 	error = copyinstr(uname, buf, MAXPATHLEN, &dummy);
+done:
 	if (error)
 		linux_free_path(kname);
 	return (error);
@@ -176,6 +186,8 @@
 		error = 0;
 		goto cleanup;
 	}
+	NDFREE(&nd, NDF_ONLY_PNBUF);
+	vrele(nd.ni_vp);
 
 	/*
 	 * The alternate path does exist.  Return it in the buffer if
Index: i386/linprocfs/linprocfs_vnops.c
===================================================================
RCS file: /cvs/src/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c,v
retrieving revision 1.16
diff -u -r1.16 linprocfs_vnops.c
--- i386/linprocfs/linprocfs_vnops.c	17 Aug 2004 18:57:32 -0000	1.16
+++ i386/linprocfs/linprocfs_vnops.c	4 Sep 2004 04:16:50 -0000
@@ -632,13 +632,8 @@
 }
 
 /*
- * lookup.  this is incredibly complicated in the
- * general case, however for most pseudo-filesystems
- * very little needs to be done.
- *
- * unless you want to get a migraine, just make sure your
- * filesystem doesn't do any locking of its own.  otherwise
- * read and inwardly digest ufs_lookup().
+ * lookup.  this is incredibly complicated in the general case, however
+ * for most pseudo-filesystems very little needs to be done.
  */
 static int
 linprocfs_lookup(ap)
@@ -657,6 +652,7 @@
 	struct pfsnode *pfs;
 	struct proc *p;
 	int i;
+	int error;
 
 	*vpp = NULL;
 
@@ -666,11 +662,12 @@
 		return (EROFS);
 	}
 
+	error = 0;
+
 	if (cnp->cn_namelen == 1 && *pname == '.') {
 		*vpp = dvp;
-		vref(dvp);
-		/* vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, curp); */
-		return (0);
+		vref(*vpp);
+		goto out;
 	}
 
 	pfs = VTOPFS(dvp);
@@ -679,20 +676,34 @@
 		if (cnp->cn_flags & CNP_ISDOTDOT)
 			return (EIO);
 
-		if (CNEQ(cnp, "self", 4))
-			return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Pself));
-		if (CNEQ(cnp, "meminfo", 7))
-			return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Pmeminfo));
-		if (CNEQ(cnp, "cpuinfo", 7))
-			return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Pcpuinfo));
-		if (CNEQ(cnp, "stat", 4))
-			return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Pstat));
-		if (CNEQ(cnp, "uptime", 6))
-			return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Puptime));
-		if (CNEQ(cnp, "version", 7))
-			return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Pversion));
-		if (CNEQ(cnp, "loadavg", 7))
-			return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Ploadavg));
+		if (CNEQ(cnp, "self", 4)) {
+			error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Pself);
+			goto out;
+		}
+		if (CNEQ(cnp, "meminfo", 7)) {
+			error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Pmeminfo);
+			goto out;
+		}
+		if (CNEQ(cnp, "cpuinfo", 7)) {
+			error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Pcpuinfo);
+			goto out;
+		}
+		if (CNEQ(cnp, "stat", 4)) {
+			error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Pstat);
+			goto out;
+		}
+		if (CNEQ(cnp, "uptime", 6)) {
+			error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Puptime);
+			goto out;
+		}
+		if (CNEQ(cnp, "version", 7)) {
+			error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Pversion);
+			goto out;
+		}
+		if (CNEQ(cnp, "loadavg", 7)) {
+			error = linprocfs_allocvp(dvp->v_mount, vpp, 0, Ploadavg);
+			goto out;
+		}
 
 		pid = atopid(pname, cnp->cn_namelen);
 		if (pid == NO_PID)
@@ -702,11 +713,14 @@
 		if (p == 0)
 			break;
 
-		return (linprocfs_allocvp(dvp->v_mount, vpp, pid, Pproc));
+		error = linprocfs_allocvp(dvp->v_mount, vpp, pid, Pproc);
+		goto out;
 
 	case Pproc:
-		if (cnp->cn_flags & CNP_ISDOTDOT)
-			return (linprocfs_root(dvp->v_mount, vpp));
+		if (cnp->cn_flags & CNP_ISDOTDOT) {
+			error = linprocfs_root(dvp->v_mount, vpp);
+			goto out;
+		}
 
 		p = PFIND(pfs->pfs_pid);
 		if (p == 0)
@@ -721,14 +735,33 @@
 		break;
 
 	found:
-		return (linprocfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
-		    pt->pt_pfstype));
+		error = linprocfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
+					pt->pt_pfstype);
+		goto out;
 
 	default:
-		return (ENOTDIR);
+		error = ENOTDIR;
+		goto out;
 	}
 
-	return (cnp->cn_nameiop == NAMEI_LOOKUP ? ENOENT : EROFS);
+	if (cnp->cn_nameiop == NAMEI_LOOKUP)
+		error = ENOENT;
+	else
+		error = EROFS;
+
+	/*
+	 * If no error occured *vpp will hold a referenced locked vnode.
+	 * dvp was passed to us locked and *vpp must be returned locked
+	 * so if dvp != *vpp and CNP_LOCKPARENT is not set, unlock dvp.
+	 */
+out:
+	if (error == 0) {
+		if (*vpp != dvp && (cnp->cn_flags & CNP_LOCKPARENT) == 0) {
+			cnp->cn_flags |= CNP_PDIRUNLOCK;
+			VOP_UNLOCK(dvp, NULL, 0, cnp->cn_td);
+		}
+	}
+	return (error);
 }
 
 /*





More information about the Bugs mailing list