Messages in this thread Patch in this message | | | Date | Tue, 12 Sep 2006 16:07:03 +0800 | From | Aubrey <> | Subject | Re: kernel BUGs when removing largish files with the SLOB allocator |
| |
On 9/6/06, Nick Piggin <nickpiggin@yahoo.com.au> wrote: > Aubrey wrote: > > > Yeah, I agree with most of your opinion. Using PG_slab is really a > > quickest way to determine the size of the object. But I think using a > > flag named "PG_slab" on a memory algorithm named "slob" seems not > > reasonable. It may confuse the people who start to read the kernel > > source code. So I'm writing to ask if there is a better solution to > > fix the issue. > > > No, confusing would be a "slab replacement" that doesn't provide the same > API as slab and thus requires users to use ifdefs. > > I've already suggested exact same thing as David in the exact same situation > about 6 months ago. It is the right way to go.
OK. Here is the patch and work properly on my side. Welcome any suggestions and comments.
Thanks, -Aubrey ================================================================= diff --git a/mm/slob.c b/mm/slob.c index 7b52b20..18ed170 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -109,6 +109,7 @@ static void *slob_alloc(size_t size, gfp
slob_free(cur, PAGE_SIZE); spin_lock_irqsave(&slob_lock, flags); + SetPageSlab(virt_to_page(cur)); cur = slobfree; } } @@ -162,6 +163,8 @@ void *kmalloc(size_t size, gfp_t gfp) slob_t *m; bigblock_t *bb; unsigned long flags; + int i; + struct page *page;
if (size < PAGE_SIZE - SLOB_UNIT) { m = slob_alloc(size + SLOB_UNIT, gfp, 0); @@ -173,12 +176,17 @@ void *kmalloc(size_t size, gfp_t gfp) return 0;
bb->order = find_order(size); - bb->pages = (void *)__get_free_pages(gfp, bb->order); + page = alloc_pages(gfp, bb->order); + bb->pages = (void *)page_address(page);
if (bb->pages) { spin_lock_irqsave(&block_lock, flags); bb->next = bigblocks; bigblocks = bb; + for (i = 0; i < (1 << bb->order); i++) { + SetPageSlab(page); + page++; + } spin_unlock_irqrestore(&block_lock, flags); return bb->pages; } @@ -202,8 +210,16 @@ void kfree(const void *block) spin_lock_irqsave(&block_lock, flags); for (bb = bigblocks; bb; last = &bb->next, bb = bb->next) { if (bb->pages == block) { + struct page *page = virt_to_page(bb->pages); + int i; + *last = bb->next; spin_unlock_irqrestore(&block_lock, flags); + for (i = 0; i < (1 << bb->order); i++) { + if (!TestClearPageSlab(page)) + BUG(); + page++; + } free_pages((unsigned long)block, bb->order); slob_free(bb, sizeof(bigblock_t)); return; @@ -332,10 +348,12 @@ static struct timer_list slob_timer = TI
void kmem_cache_init(void) { +#if 0 void *p = slob_alloc(PAGE_SIZE, 0, PAGE_SIZE-1);
if (p) free_page((unsigned long)p); +#endif
mod_timer(&slob_timer, jiffies + HZ); } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |