Re: "panic: fxp_start_body: attempted use of a free mbuf!" in RELENG_5

From: Brian Fundakowski Feldman <green_at_FreeBSD.org>
Date: Thu, 7 Oct 2004 16:48:44 -0400
On Thu, Oct 07, 2004 at 09:57:19AM -0700, Kris Kennaway wrote:
> Top of RELENG_5 on an smp machine:
> 
> panic: fxp_start_body: attempted use of a free mbuf!
> cpuid = 1
> KDB: enter: panic
> [thread 100042]
> Stopped at      kdb_enter+0x30: leave
> db> trace
> kdb_enter(c06de69a,1,c06d47c5,ebbd2b14,c34cd320) at kdb_enter+0x30
> panic(c06d47c5,c06c1030,4,c0499300,c3539000) at panic+0x14e
> fxp_start_body(c3539000,0,c06d5639,4ca,c3539000) at fxp_start_body+0x462
> fxp_start(c3539000,122,0,c3539000) at fxp_start+0x3f
> if_start(c3539000,0,c06e7822,179,ffff8002) at if_start+0x99
> ether_output_frame(c3539000,c38b5300,6,c4106b00,ebbd2bc8) at ether_output_frame+0x218
> ether_output(c3539000,c38b5300,c4106b00,c95ec210,c04fe48d) at ether_output+0x43e
> in_arpinput(c38b8700,122,c38b8700,c07656b8,c38b8700) at in_arpinput+0x686
> arpintr(c38b8700,0,c06e7c88,e5,c07656b8) at arpintr+0x104
> netisr_processqueue(c07656b8,c0738ac0,1,c06dda24,c3462940) at netisr_processqueue+0x8e
> swi_net(0,0,c06dc037,269,c0738ac0) at swi_net+0xe9
> ithread_loop(c345d880,ebbd2d48,c06dbe2a,323,d552d9c9) at ithread_loop+0x172
> fork_exit(c04f1210,c345d880,ebbd2d48) at fork_exit+0xc6
> fork_trampoline() at fork_trampoline+0x8
> --- trap 0x1, eip = 0, esp = 0xebbd2d7c, ebp = 0 ---

Does this fix it?

Index: uma_core.c
===================================================================
RCS file: /usr/ncvs/src/sys/vm/uma_core.c,v
retrieving revision 1.105
diff -u -r1.105 uma_core.c
--- uma_core.c	6 Aug 2004 21:52:38 -0000	1.105
+++ uma_core.c	7 Oct 2004 20:31:08 -0000
_at__at_ -825,13 +825,16 _at__at_
 	slab->us_freecount = keg->uk_ipers;
 	slab->us_firstfree = 0;
 	slab->us_flags = flags;
-	for (i = 0; i < keg->uk_ipers; i++)
-		slab->us_freelist[i].us_item = i+1;
 
 	if (keg->uk_flags & UMA_ZONE_REFCNT) {
 		slabref = (uma_slabrefcnt_t)slab;
-		for (i = 0; i < keg->uk_ipers; i++)
+		for (i = 0; i < keg->uk_ipers; i++) {
 			slabref->us_freelist[i].us_refcnt = 0;
+			slabref->us_freelist[i].us_item = i+1;
+		}
+	} else {
+		for (i = 0; i < keg->uk_ipers; i++)
+			slab->us_freelist[i].us_item = i+1;
 	}
 
 	if (keg->uk_init != NULL) {
_at__at_ -1983,13 +1986,19 _at__at_
 uma_slab_alloc(uma_zone_t zone, uma_slab_t slab)
 {
 	uma_keg_t keg;
+	uma_slabrefcnt_t slabref;
 	void *item;
 	u_int8_t freei;
 
 	keg = zone->uz_keg;
 
 	freei = slab->us_firstfree;
-	slab->us_firstfree = slab->us_freelist[freei].us_item;
+	if (keg->uk_flags & UMA_ZONE_REFCNT) {
+		slabref = (uma_slabrefcnt_t)slab;
+		slab->us_firstfree = slabref->us_freelist[freei].us_item;
+	} else {
+		slab->us_firstfree = slab->us_freelist[freei].us_item;
+	}
 	item = slab->us_data + (keg->uk_rsize * freei);
 
 	slab->us_freecount--;
_at__at_ -2339,6 +2348,7 _at__at_
     enum zfreeskip skip)
 {
 	uma_slab_t slab;
+	uma_slabrefcnt_t slabref;
 	uma_keg_t keg;
 	u_int8_t *mem;
 	u_int8_t freei;
_at__at_ -2382,7 +2392,12 _at__at_
 		uma_dbg_free(zone, slab, item);
 #endif
 
-	slab->us_freelist[freei].us_item = slab->us_firstfree;
+	if (keg->uk_flags & UMA_ZONE_REFCNT) {
+		slabref = (uma_slabrefcnt_t)slab;
+		slabref->us_freelist[freei].us_item = slab->us_firstfree;
+	} else {
+		slab->us_freelist[freei].us_item = slab->us_firstfree;
+	}
 	slab->us_firstfree = freei;
 	slab->us_freecount++;
 
_at__at_ -2545,18 +2560,19 _at__at_
 u_int32_t *
 uma_find_refcnt(uma_zone_t zone, void *item)
 {
-	uma_slabrefcnt_t slab;
+	uma_slabrefcnt_t slabref;
 	uma_keg_t keg;
 	u_int32_t *refcnt;
 	int idx;
 
 	keg = zone->uz_keg;
-	slab = (uma_slabrefcnt_t)vtoslab((vm_offset_t)item & (~UMA_SLAB_MASK));
-	KASSERT(slab != NULL,
+	slabref = (uma_slabrefcnt_t)vtoslab((vm_offset_t)item &
+	    (~UMA_SLAB_MASK));
+	KASSERT(slabref != NULL && slabref->us_keg->uk_flags & UMA_ZONE_REFCNT,
 	    ("uma_find_refcnt(): zone possibly not UMA_ZONE_REFCNT"));
-	idx = ((unsigned long)item - (unsigned long)slab->us_data)
+	idx = ((unsigned long)item - (unsigned long)slabref->us_data)
 	    / keg->uk_rsize;
-	refcnt = &(slab->us_freelist[idx].us_refcnt);
+	refcnt = &slabref->us_freelist[idx].us_refcnt;
 	return refcnt;
 }
 
Index: uma_dbg.c
===================================================================
RCS file: /usr/ncvs/src/sys/vm/uma_dbg.c,v
retrieving revision 1.15
diff -u -r1.15 uma_dbg.c
--- uma_dbg.c	2 Aug 2004 00:18:35 -0000	1.15
+++ uma_dbg.c	7 Oct 2004 20:35:22 -0000
_at__at_ -218,6 +218,7 _at__at_
 uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item)
 {
 	uma_keg_t keg;
+	uma_slabrefcnt_t slabref;
 	int freei;
 
 	keg = zone->uz_keg;
_at__at_ -231,7 +232,12 _at__at_
 	freei = ((unsigned long)item - (unsigned long)slab->us_data)
 	    / keg->uk_rsize;
 
-	slab->us_freelist[freei].us_item = 255;
+	if (keg->uk_flags & UMA_ZONE_REFCNT) {
+		slabref = (uma_slabrefcnt_t)slab;
+		slabref->us_freelist[freei].us_item = 255;
+	} else {
+		slab->us_freelist[freei].us_item = 255;
+	}
 
 	return;
 }
_at__at_ -246,6 +252,7 _at__at_
 uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item)
 {
 	uma_keg_t keg;
+	uma_slabrefcnt_t slabref;
 	int freei;
 
 	keg = zone->uz_keg;
_at__at_ -270,17 +277,34 _at__at_
 		    (freei * keg->uk_rsize) + slab->us_data);
 	}
 
-	if (slab->us_freelist[freei].us_item != 255) {
-		printf("Slab at %p, freei %d = %d.\n",
-		    slab, freei, slab->us_freelist[freei].us_item);
-		panic("Duplicate free of item %p from zone %p(%s)\n",
-		    item, zone, zone->uz_name);
+	if (keg->uk_flags & UMA_ZONE_REFCNT) {
+		slabref = (uma_slabrefcnt_t)slab;
+		if (slabref->us_freelist[freei].us_item != 255) {
+			printf("Slab at %p, freei %d = %d.\n",
+			    slab, freei, slabref->us_freelist[freei].us_item);
+			panic("Duplicate free of item %p from zone %p(%s)\n",
+			    item, zone, zone->uz_name);
+		}
+
+		/*
+		 * When this is actually linked into the slab this will change.
+		 * Until then the count of valid slabs will make sure we don't
+		 * accidentally follow this and assume it's a valid index.
+		 */
+		slabref->us_freelist[freei].us_item = 0;
+	} else {
+		if (slab->us_freelist[freei].us_item != 255) {
+			printf("Slab at %p, freei %d = %d.\n",
+			    slab, freei, slab->us_freelist[freei].us_item);
+			panic("Duplicate free of item %p from zone %p(%s)\n",
+			    item, zone, zone->uz_name);
+		}
+
+		/*
+		 * When this is actually linked into the slab this will change.
+		 * Until then the count of valid slabs will make sure we don't
+		 * accidentally follow this and assume it's a valid index.
+		 */
+		slab->us_freelist[freei].us_item = 0;
 	}
-
-	/*
-	 * When this is actually linked into the slab this will change.
-	 * Until then the count of valid slabs will make sure we don't
-	 * accidentally follow this and assume it's a valid index.
-	 */
-	slab->us_freelist[freei].us_item = 0;
 }

-- 
Brian Fundakowski Feldman                           \'[ FreeBSD ]''''''''''\
  <> green_at_FreeBSD.org                               \  The Power to Serve! \
 Opinions expressed are my own.                       \,,,,,,,,,,,,,,,,,,,,,,\
Received on Thu Oct 07 2004 - 18:48:47 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:16 UTC