panic with heavy writing on md device

Brian Fundakowski Feldman green at freebsd.org
Tue Jun 29 16:52:23 PDT 2004


On Tue, Jun 29, 2004 at 11:11:51PM +0200, Ronald Klop wrote:
> Hello,
> 
> I got a panic while doing a lot of IO on a md device.
> I attached a gdb backtrace of the kernelcore and a dmesg output.
> 
> It happened while untarring a 30 MB tar on the background (&) and
> traversing this new directory in the meantime.
> 
> uname -a
> FreeBSD guido.thuis.klop.ws 5.2-CURRENT FreeBSD 5.2-CURRENT #1: Fri Jun 25  
> 04:03:35 CEST 2004      
> root at guido.thuis.klop.ws:/usr/obj/usr/src/sys/GUIDO  i386
> 
> On the same time I was playing music with mpg123, but that doesn't make  
> use of the md device.
> 
> I have had this more and always while doing a lot of IO on the md device.
> 
> Is there more info you need?

It looks like there is a memory leak -- in general, you are not supposed
to run out of kernel virtual memory address space unless you have a
dire misconfiguration somewhere.

Unfortunately, I think the most useful pieces of information (zone and
malloc allocation) are not fetchable via kvm anymore.  Here's a fix for
vmstat so that you can provide vmstat -m output using the -M and -N
args again.  I think vmstat -c output would also be useful.

-- 
Brian Fundakowski Feldman                           \'[ FreeBSD ]''''''''''\
  <> green at FreeBSD.org                               \  The Power to Serve! \
 Opinions expressed are my own.                       \,,,,,,,,,,,,,,,,,,,,,,\
-------------- next part --------------
Index: vmstat.c
===================================================================
RCS file: /usr/ncvs/src/usr.bin/vmstat/vmstat.c,v
retrieving revision 1.82
diff -u -r1.82 vmstat.c
--- vmstat.c	23 Apr 2004 13:10:29 -0000	1.82
+++ vmstat.c	29 Jun 2004 23:36:57 -0000
@@ -99,18 +99,22 @@
 	{ "_intrcnt" },
 #define	X_EINTRCNT	9
 	{ "_eintrcnt" },
+#define	X_KMEMSTATS	10
+	{ "_kmemstatistics" },
+#define	X_KMEMZONES	11
+	{ "_kmemzones" },
 #ifdef notyet
-#define	X_DEFICIT	10
+#define	X_DEFICIT	XXX
 	{ "_deficit" },
-#define X_REC		11
+#define X_REC		XXX
 	{ "_rectime" },
-#define X_PGIN		12
+#define X_PGIN		XXX
 	{ "_pgintime" },
-#define	X_XSTATS	13
+#define	X_XSTATS	XXX
 	{ "_xstats" },
-#define X_END		14
+#define X_END		XXX
 #else
-#define X_END		10
+#define X_END		12
 #endif
 	{ "" },
 };
@@ -153,6 +157,8 @@
 static void	dovmstat(unsigned int, int);
 static void	dozmem(void);
 static void	kread(int, void *, size_t);
+static void	kreado(int, void *, size_t, size_t);
+static char    *kgetstr(const char *);
 static void	needhdr(int);
 static void	printhdr(void);
 static void	usage(void);
@@ -894,9 +900,59 @@
 static void
 domem(void)
 {
-	if (kd != NULL)
-		errx(1, "not implemented");
-	dosysctl("kern.malloc");
+	struct malloc_type type;
+	
+	if (kd == NULL) {
+		dosysctl("kern.malloc");
+		return;
+	}
+	kread(X_KMEMSTATS, &type.ks_next, sizeof(type.ks_next));
+	(void)printf("\n        Type  InUse MemUse HighUse Requests"
+	    "  Size(s)\n");
+	do { 
+		/* XXX this should be exported in sys/malloc.h */
+		struct {
+			int kz_size;
+			char *kz_name;
+			/* uma_zone_t */ void *kz_zone;
+		} kz;
+		size_t kmemzonenum;
+		char *str;
+		int first;
+
+		if (kvm_read(kd, (u_long)type.ks_next, &type, sizeof(type)) !=
+		    sizeof(type))
+			errx(1, "%s: %p: %s", __func__, type.ks_next,
+			    kvm_geterr(kd));
+		if (type.ks_calls == 0)
+			continue;
+		str = kgetstr(type.ks_shortdesc);
+		(void)printf("%13s%6lu%6luK%7luK%9llu",
+		    str,
+		    type.ks_inuse,
+		    (type.ks_memuse + 1023) / 1024,
+		    (type.ks_maxused + 1023) / 1024,
+		    (long long unsigned)type.ks_calls);
+		free(str);
+		for (kmemzonenum = 0, first = 1; ; kmemzonenum++) {
+			kreado(X_KMEMZONES, &kz, sizeof(kz),
+			    kmemzonenum * sizeof(kz));
+			if (kz.kz_name == NULL) {
+				(void)printf("\n");
+				break;
+			}
+			if (!(type.ks_size & (1 << kmemzonenum)))
+				continue;
+			if (first)
+				(void)printf("  ");
+			else
+				(void)printf(",");
+			first = 0;
+			str = kgetstr(kz.kz_name);
+			(void)printf("%s", str);
+			free(str);
+		}
+	} while (type.ks_next != NULL);
 }
 
 static void
@@ -929,7 +985,7 @@
  * kread reads something from the kernel, given its nlist index.
  */
 static void
-kread(int nlx, void *addr, size_t size)
+kreado(int nlx, void *addr, size_t size, size_t offset)
 {
 	const char *sym;
 
@@ -939,12 +995,38 @@
 			++sym;
 		errx(1, "symbol %s not defined", sym);
 	}
-	if ((size_t)kvm_read(kd, namelist[nlx].n_value, addr, size) != size) {
+	if ((size_t)kvm_read(kd, namelist[nlx].n_value + offset, addr,
+	    size) != size) {
 		sym = namelist[nlx].n_name;
 		if (*sym == '_')
 			++sym;
 		errx(1, "%s: %s", sym, kvm_geterr(kd));
 	}
+}
+
+static void
+kread(int nlx, void *addr, size_t size)
+{
+	kreado(nlx, addr, size, 0);
+}
+
+static char *
+kgetstr(const char *strp)
+{
+	int n = 0, size = 1;
+	char *ret = NULL;
+
+	do {
+		if (size == n + 1) {
+			ret = realloc(ret, size);
+			if (ret == NULL)
+				err(1, "%s: realloc", __func__);
+			size *= 2;
+		}
+		if (kvm_read(kd, (u_long)strp + n, &ret[n], 1) != 1)
+			errx(1, "%s: %s", __func__, kvm_geterr(kd));
+	} while (ret[n++] != '\0');
+	return (ret);
 }
 
 static void


More information about the freebsd-current mailing list