We are experiencing what appears to be a memory corruption problem with a kernel device driver running under FreeBSD 2.2.8-STABLE with the CAM patches.
The driver manages a series of memory buffers implemented using a singly-linked tail list. The number and size of buffers may be changed via an ioctl call which causes all of the currently-allocated buffers (one per tail list element) to be deallocated, and a new set - matching the required buffer size - to be malloc'ed. The tail queue holding the newly- allocated buffers is a local copy, and not subject to change in the event of an interrupt meant for the driver. Given certain choices for the size and number of buffers, we are observing corruption of the local copy of the tail queue during and after the memory allocation process. The corruption usually takes the form of a NULL pointer overwriting the linking member of a queue element somewhere in the list, thus rendering some protions of the allocated memory to be "lost", or non-free-able. The particular combination of buffer size and number of buffers which exhibits the problem is: buffer_size = 8k + 8 bytes (8k buffer + link pointer etc) num_buffers >= 22. If less than 22 buffers are allocated, the list appears to remain intact. I'm not sure if it's relavant, but I note that 22 * 8k is just over the 256 kb size, while 21 * 8k is less than this total. Here is the snipet of code which builds the list -> STAILQ_INIT(&buildlist); gsio_tossbuffers(sc); /* dump old buffers */ i = args->value; while(i--) { /* allocate required buffers */ gb = malloc(sizeof(struct gsio_buf) + args->which, M_DEVBUF, M_NOWAIT); debug(BUF2, "g_freelist +> %p", gb); if (gb == NULL) { /* allocate failed, toss all * buffers */ debug(BUF, "failed to allocate buffers, freeing"); while ((gb = STAILQ_FIRST(&buildlist)) != NULL) { STAILQ_REMOVE_HEAD(&buildlist, g_link); free(gb, M_DEVBUF); } error = ENOMEM; break; } else { STAILQ_INSERT_HEAD(&buildlist, gb, g_link); debug(BUF, "New buffer at %p length 0x%x, next is %p ,tail is %p", gb, sizeof(struct gsio_buf) + args->which, gb->g_link.stqe_next, buildlist.stqh_last); } } --- Daniel O'Connor software and network engineer for Genesis Software - http://www.gsoft.com.au "The nice thing about standards is that there are so many of them to choose from." -- Andrew Tanenbaum
pgpW4KKiLTChh.pgp
Description: PGP signature