DragonFly BSD
DragonFly bugs List (threaded) for 2004-09
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

Re: "busy buffer problem" panics


From: Matthew Dillon <dillon@xxxxxxxxxxxxxxxxxxxx>
Date: Thu, 2 Sep 2004 21:58:03 -0700 (PDT)

:
:This box is both an nfs client (about 20 static mount points) and a server
:(about 5 clients, several mount points), and I'm running amd so it's
:automounting on /net a lot, especially during many clearcase operations.=20
:
:Not sure if 'cleartool lsact -l' does anything with /net but it is possible.
:
:I'm thinking that locking in the linuxulator is at the root of this ...
:
:Andrew.

    Try this patch with the latest kernel.  The failure case is odd, because
    it looks like the underlying lock is somehow entering the system
    shutdown code.  The code in linux_util appears to have some severe
    leaks: a vnode reference count leak and a memory leak, which thi
    s patch fixes.

    Does running clearcase crash it immediately or does it take a number of
    runs?  For the reference count to be causing the problem, the vnode
    would have to cycle through 2-4 billion accesses (to wrap the ref count).
    This is certainly possible, but it would take a while.

					-Matt
					Matthew Dillon 
					<dillon@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



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