Date: Mon, 2 Nov 1998 21:35:37 -0500 (EST) From: "Larry S. Lile" <lile@stdio.com> To: hackers@FreeBSD.ORG Subject: "panic: free: multiple frees" VM bug? (long) Message-ID: <Pine.BSF.3.96.981102212308.17694B-100000@heathers.stdio.com>
index | next in thread | raw e-mail
I am working on a token ring driver and I cannot seem to find
out why this is happening. I contigmalloc buffers for tranmsitting
frames and then free them later when they have been transmitted.
I have to use contigmalloc in order to get buffers below the
16M mark for dma.
Anyone see what is wrong? Should I not do this? Or have I
stumbled over a vm bug?
It looks like a vm bug to me, but I have been wrong before.
All pertinent information below...
Larry Lile
lile@stdio.com
Please ignore the soft-updates panic, I understand that happens
sometimes during a dump.
panicstr: page fault
panic messages:
---
panic: free: multiple frees
syncing disks...
Fatal trap 12: page fault while in kernel mode
fault virtual address = 0x30
fault code = supervisor read, page not present
instruction pointer = 0x8:0xf01cdf08
stack pointer = 0x10:0xf024bf14
frame pointer = 0x10:0xf024bf18
code segment = base 0x0, limit 0xfffff, type 0x1b
= DPL 0, pres 1, def32 1, gran 1
processor eflags = interrupt enabled, resume, IOPL = 0
current process = Idle
interrupt mask = net tty bio cam
trap number = 12
panic: page fault
---
#0 boot (howto=260) at ../../kern/kern_shutdown.c:268
268 dumppcb.pcb_cr3 = rcr3();
(kgdb) bt
#0 boot (howto=260) at ../../kern/kern_shutdown.c:268
#1 0xf014932f in panic (fmt=0xf0242de9 "page fault")
at ../../kern/kern_shutdown.c:430
#2 0xf01f796d in trap_fatal (frame=0xf024bed8) at
../../i386/i386/trap.c:879
#3 0xf01f7648 in trap_pfault (frame=0xf024bed8, usermode=0)
at ../../i386/i386/trap.c:772
#4 0xf01f72a7 in trap (frame={tf_es = 16, tf_ds = 16, tf_edi = 0,
tf_esi = -252868608, tf_ebp = -266027240, tf_isp = -266027264,
tf_ebx = -265970844, tf_edx = -1073217472, tf_ecx = 0, tf_eax = 0,
tf_trapno = 12, tf_err = 0, tf_eip = -266543352, tf_cs = 8,
tf_eflags = 66182, tf_esp = -252868608, tf_ss = -266027208})
at ../../i386/i386/trap.c:396
#5 0xf01cdf08 in acquire_lock (lk=0xf0259b64)
at ../../ufs/ffs/ffs_softdep.c:268
#6 0xf01d1929 in softdep_update_inodeblock (ip=0xf0ed8800, bp=0xf368ac30,
waitfor=0) at ../../ufs/ffs/ffs_softdep.c:3482
#7 0xf01ccf1c in ffs_update (vp=0xf5ddc0c0, access=0xf024bfd0,
modify=0xf024bfd0, waitfor=0) at ../../ufs/ffs/ffs_inode.c:109
#8 0xf01d5f59 in ffs_fsync (ap=0xf024c00c) at
../../ufs/ffs/ffs_vnops.c:252
#9 0xf01d4383 in ffs_sync (mp=0xf0e40a00, waitfor=2, cred=0xf0dd3700,
p=0xf028a04c) at vnode_if.h:499
#10 0xf016b2a7 in sync (p=0xf028a04c, uap=0x0) at
../../kern/vfs_syscalls.c:527
#11 0xf0148faa in boot (howto=256) at ../../kern/kern_shutdown.c:201
#12 0xf014932f in panic (fmt=0xf023723e "free: multiple frees")
at ../../kern/kern_shutdown.c:430
#13 0xf0146553 in free (addr=0xf5e62000, type=0xf0251980)
at ../../kern/kern_malloc.c:334
#14 0xf01febe3 in DriverTransmitFrameCompleted (DriverHandle=0x0,
FrameHandle=0xa, TransmitStatus=0) at ../../i386/isa/if_oltr.c:936
#15 0xf022b252 in ReturnCompletedBuffers ()
#16 0x30001 in ?? ()
cannot read proc at 0
(kgdb) up 14
#14 0xf01febe3 in DriverTransmitFrameCompleted (DriverHandle=0x0,
FrameHandle=0xa, TransmitStatus=0) at ../../i386/isa/if_oltr.c:936
936
free(sc->tx_buffer[frame].frame->TransmitFragment[i].VirtualAddress,
M_DEVBUF);
(kgdb) list
931 printf("oltr%d: Unused buffer returned *boggle*\n",
sc->unit);
932 } else {
933 for (i = 0; i < sc->tx_buffer[frame].frame->FragmentCount;
i++) {
934 printf("oltr%d: freeing fragment %d frame %d\n",
sc->unit, i, frame);
935 sc->tx_frags--;
936
free(sc->tx_buffer[frame].frame->TransmitFragment[i].VirtualAddress,
M_DEVBUF);
937 }
938 }
939
940 printf("Oltr%d: %d total frags in use.\n", sc->unit,
sc->tx_frags);
(kgdb)
I know that I have not called free on the same buffer twice by
looking at the debug messages.
Nov 2 21:11:43 anarchy /kernel: oltr0: output frame 0 - 1 fragments (1
fragments in use total)
Nov 2 21:11:43 anarchy /kernel: iso88025_input: Packet queued.
Nov 2 21:11:43 anarchy /kernel: oltr0: transmit complete frame 0 - 1
fragments (1 total fragments in use total)
Nov 2 21:11:43 anarchy /kernel: oltr0: freeing fragment 0 frame 0
Nov 2 21:11:43 anarchy /kernel: Oltr0: 0 total frags in use.
Nov 2 21:11:56 anarchy /kernel: oltr0: output frame 1 - 1 fragments (1
fragments in use total)
Nov 2 21:11:56 anarchy /kernel: iso88025_input: Packet queued.
Nov 2 21:11:56 anarchy /kernel: oltr0: transmit complete frame 1 - 1
fragments (1 total fragments in use total)
Nov 2 21:11:56 anarchy /kernel: oltr0: freeing fragment 0 frame 1
Nov 2 21:11:56 anarchy /kernel: Oltr0: 0 total frags in use.
Nov 2 21:11:56 anarchy /kernel: iso88025_input: Packet queued.
Nov 2 21:11:56 anarchy /kernel: oltr0: output frame 2 - 2 fragments (2
fragments in use total)
Nov 2 21:11:56 anarchy /kernel: oltr0: transmit complete frame 2 - 2
fragments (2 total fragments in use total)
Nov 2 21:11:56 anarchy /kernel: oltr0: freeing fragment 0 frame 2
Nov 2 21:11:56 anarchy /kernel: oltr0: freeing fragment 1 frame 2
Nov 2 21:11:57 anarchy /kernel: Oltr0: 0 total frags in use.
Nov 2 21:11:57 anarchy /kernel: iso88025_input: Packet queued.
Nov 2 21:11:57 anarchy /kernel: oltr0: output frame 3 - 1 fragments (1
fragments in use total)
Nov 2 21:11:57 anarchy /kernel: oltr0: transmit complete frame 3 - 1
fragments (1 total fragments in use total)
Nov 2 21:11:57 anarchy /kernel: oltr0: freeing fragment 0 frame 3
Nov 2 21:11:57 anarchy /kernel: Oltr0: 0 total frags in use.
Nov 2 21:11:59 anarchy /kernel: oltr0: output frame 4 - 2 fragments (2
fragments in use total)
Nov 2 21:11:59 anarchy /kernel: oltr0: transmit complete frame 4 - 2
fragments (2 total fragments in use total)
Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 0 frame 4
Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 1 frame 4
Nov 2 21:11:59 anarchy /kernel: Oltr0: 0 total frags in use.
Nov 2 21:11:59 anarchy /kernel: iso88025_input: Packet queued.
Nov 2 21:11:59 anarchy /kernel: oltr0: output frame 5 - 2 fragments (2
fragments in use total)
Nov 2 21:11:59 anarchy /kernel: oltr0: transmit complete frame 5 - 2
fragments (2 total fragments in use total)
Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 0 frame 5
Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 1 frame 5
Nov 2 21:11:59 anarchy /kernel: Oltr0: 0 total frags in use.
Nov 2 21:11:59 anarchy /kernel: oltr0: output frame 6 - 2 fragments (2
fragments in use total)
Nov 2 21:11:59 anarchy /kernel: oltr0: transmit complete frame 6 - 2
fragments (2 total fragments in use total)
Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 0 frame 6
Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 1 frame 6
Nov 2 21:11:59 anarchy /kernel: Oltr0: 0 total frags in use.
Nov 2 21:11:59 anarchy /kernel: iso88025_input: Packet queued.
Nov 2 21:11:59 anarchy /kernel: oltr0: output frame 7 - 2 fragments (2
fragments in use total)
Nov 2 21:11:59 anarchy /kernel: oltr0: transmit complete frame 7 - 2
fragments (2 total fragments in use total)
Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 0 frame 7
Nov 2 21:11:59 anarchy /kernel: oltr0: freeing fragment 1 frame 7
Nov 2 21:11:59 anarchy /kernel: Oltr0: 0 total frags in use.
How the buffers get allocated:
void *
oltr_malloc(Size, Adapter)
ssize_t Size;
TRlldAdapterConfig_t *Adapter;
{
/* If the adapter needs memory below 16M for DMA then use contigmalloc
*/
if (Adapter->mode & TRLLD_MODE_16M) /* Adapter using ISA DMA buffer
below 16M */
return(contigmalloc(Size, M_DEVBUF, M_NOWAIT, 0ul, 0xfffffful,
1ul, 0x10000ul));
else
return(malloc(Size, M_DEVBUF, M_NOWAIT));
}
Where the frames get built:
static void
oltr_start(ifp)
struct ifnet *ifp;
{
struct oltr_softc *sc = &oltr_softc[ifp->if_unit];
struct mbuf *m0, *m;
struct iso88025_header *th;
int len, i, j, k, rc, s;
/*printf("oltr%d: oltr_start\n", sc->unit);*/
s = splimp();
/* Check to see if we have enough room to transmit */
if (sc->tx_avail <= 0) {
/* No free buffers, hold off the upper layers */
/*printf("oltr%d: transmit queue full.\n", sc->unit);*/
ifp->if_flags |= IFF_OACTIVE;
splx(s);
return;
}
IF_DEQUEUE(&ifp->if_snd, m);
if (m == 0) {
printf("oltr%d: oltr_start NULL packet dequeued.\n", sc->unit);
ifp->if_flags &= ~IFF_OACTIVE;
splx(s);
return;
}
th = mtod(m, struct iso88025_header *);
th->ac = 0x10;
th->fc = 0x40;
/* Keep a pointer to the head of the packet */
m0 = m;
i = (sc->tx_next & TX_LIST_MASK); /* Just to shorten thing up */
if (sc->tx_buffer[i].inuse) {
printf("oltr%d: Transmit ring buffer blown!\n", sc->unit);
oltr_stop(sc);
splx(s);
return;
}
for (len = 0, j = 0; m != 0; m = m->m_next, j++) {
sc->tx_frags++;
sc->tx_buffer[i].frame->TransmitFragment[j].VirtualAddress = (char
*)oltr_malloc(m->m_len, sc->config);
if (!sc->tx_buffer[i].frame->TransmitFragment[j].VirtualAddress) {
printf("oltr%d: unable to allocate memory.\n", sc->unit);
/* Free up the other fragments */
for (k = 0; k < j; k++) {
sc->tx_frags--;
free(sc->tx_buffer[i].frame->TransmitFragment[k].VirtualAddress,
M_DEVBUF);
}
goto bad;
}
sc->tx_buffer[i].frame->TransmitFragment[j].PhysicalAddress =
kvtop(sc->tx_buffer[i].frame->TransmitFragment[j].VirtualAd
dress);
sc->tx_buffer[i].frame->TransmitFragment[j].count = m->m_len;
bcopy(mtod(m, caddr_t),
sc->tx_buffer[i].frame->TransmitFragment[j].VirtualAddress, m->m_len);
len += m->m_len;
}
sc->tx_buffer[i].frame->FragmentCount = j;
sc->tx_buffer[i].inuse = 1;
rc = TRlldTransmitFrame(sc->TRlldAdapter, (TRlldTransmit_t
*)sc->tx_buffer[i].frame, (void *)sc->tx_buffer[i].index);
if (rc != TRLLD_TRANSMIT_OK) {
printf("oltr%d: TRlldTransmitFrame returned (%x)\n", sc->unit,
rc);
ifp->if_oerrors++;
for (j = 0; j < sc->tx_buffer[i].frame->FragmentCount; j++) {
sc->tx_frags--;
free(sc->tx_buffer[i].frame->TransmitFragment[j].VirtualAddress,
M_DEVBUF);
}
sc->tx_buffer[i].inuse = 0;
goto bad;
}
printf("oltr%d: output frame %d - %d fragments (%d fragments in use
total)\n", sc->unit, i, sc->tx_buffer[i].frame->FragmentC
ount, sc->tx_frags);
sc->tx_next++;
sc->tx_avail--;
#if NBPFILTER > 0
if (ifp->if_bpf)
bpf_mtap(ifp, m0);
#endif
bad:
m_freem(m);
splx(s);
return;
}
Where they get freed;
static void
DriverCloseCompleted(DriverHandle)
void *DriverHandle;
{
struct oltr_softc *sc = &oltr_softc[(int)DriverHandle];
/*printf("oltr%d: DriverCloseCompleted\n", sc->unit);*/
untimeout(oltr_timeout, (void *)sc->unit, sc->oltr_ch);
wakeup_one((void *)sc->unit);
if ((sc->hw_state != HW_CLOSING) && (sc->hw_state != HW_CLOSING2) &&
(sc->hw_state != HW_CLOSED)) {
printf("oltr%d: adapter close complete called in wrong state
(%d)\n", sc->unit, sc->hw_state);
return;
}
sc->hw_state = HW_CLOSING2;
if (sc->config->dmalevel != TRLLD_DMA_PIO)
isa_dma_release(sc->config->dmalevel);
}
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.981102212308.17694B-100000>
