From owner-freebsd-hackers@FreeBSD.ORG Sat Apr 19 12:07:56 2003 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id DC50E37B401; Sat, 19 Apr 2003 12:07:56 -0700 (PDT) Received: from puffin.mail.pas.earthlink.net (puffin.mail.pas.earthlink.net [207.217.120.139]) by mx1.FreeBSD.org (Postfix) with ESMTP id 66AE943FBD; Sat, 19 Apr 2003 12:07:56 -0700 (PDT) (envelope-from tlambert2@mindspring.com) Received: from pool0234.cvx22-bradley.dialup.earthlink.net ([209.179.198.234] helo=mindspring.com) by puffin.mail.pas.earthlink.net with asmtp (SSLv3:RC4-MD5:128) (Exim 3.33 #1) id 196xgo-0000Pr-00; Sat, 19 Apr 2003 12:07:55 -0700 Message-ID: <3EA19E3C.661C9A28@mindspring.com> Date: Sat, 19 Apr 2003 12:06:36 -0700 From: Terry Lambert X-Mailer: Mozilla 4.79 [en] (Win98; U) X-Accept-Language: en MIME-Version: 1.0 To: Don Lewis References: <200304190859.h3J8xNXB016406@gw.catspoiler.org> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-ELNK-Trace: b1a02af9316fbb217a47c185c03b154d40683398e744b8a41d8c330c342e87a641950f2c415955ab350badd9bab72f9c350badd9bab72f9c350badd9bab72f9c cc: hackers@FreeBSD.org Subject: Re: Repeated similar panics on -STABLE X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Apr 2003 19:07:57 -0000 Don Lewis wrote: > Ok, here's a Reader's Digest version of the code in question: > > if (kbp->kb_next == NULL) { > kbp->kb_last = NULL; > if (size > MAXALLOCSAVE) > allocsize = roundup(size, PAGE_SIZE); > else > allocsize = 1 << indx; > npg = btoc(allocsize); > va = (caddr_t) kmem_malloc(kmem_map, (vm_size_t)ctob(npg), flags > ); > /* > * Just in case we blocked while allocating memory, > * and someone else also allocated memory for this > * bucket, don't assume the list is still empty. > */ > savedlist = kbp->kb_next; > kbp->kb_next = cp = va + (npg * PAGE_SIZE) - allocsize; > for (;;) { > freep = (struct freelist *)cp; > if (cp <= va) > break; > cp -= allocsize; > freep->next = cp; > } > freep->next = savedlist; Take an interrupt somewhere around here, and have the available entries removed from the freelist by an interrupt level driver. Or take a page fault, and have the same thing happen with page-related metadata coming from the freelist in question. > if (kbp->kb_last == NULL) > kbp->kb_last = (caddr_t)freep; > } > va = kbp->kb_next; > kbp->kb_next = ((struct freelist *)va)->next; [ ... ] > This code bothers me, though, because if allocsize ever happened to not > evenly divide (npg * PAGE_SIZE), the loop termination condition would be > wrong and the end of the previous page (or more) would end up on the > free list. If va were small enough and allocsize were big enough, it > would even be possible to wrap around. That actually can't happen. Basically, the allocators "waste" the ends of pages. See the: if (cp <= va) break; cp -= allocsize; ? The "<= saves you. -- Terry