• M
    bootmem allocator: alloc_bootmem_core(): page-align the end offset · 627240aa
    Mikulas Patocka 提交于
    This is the minimal sequence that jams the allocator:
    
    void *p, *q, *r;
    p = alloc_bootmem(PAGE_SIZE);
    q = alloc_bootmem(64);
    free_bootmem(p, PAGE_SIZE);
    p = alloc_bootmem(PAGE_SIZE);
    r = alloc_bootmem(64);
    
    after this sequence (assuming that the allocator was empty or page-aligned
    before), pointer "q" will be equal to pointer "r".
    
    What's hapenning inside the allocator:
    p = alloc_bootmem(PAGE_SIZE);
    in allocator: last_end_off == PAGE_SIZE, bitmap contains bits 10000...
    q = alloc_bootmem(64);
    in allocator: last_end_off == PAGE_SIZE + 64, bitmap contains 11000...
    free_bootmem(p, PAGE_SIZE);
    in allocator: last_end_off == PAGE_SIZE + 64, bitmap contains 01000...
    p = alloc_bootmem(PAGE_SIZE);
    in allocator: last_end_off == PAGE_SIZE, bitmap contains 11000...
    r = alloc_bootmem(64);
    
    and now:
    
    it finds bit "2", as a place where to allocate (sidx)
    
    it hits the condition
    
    if (bdata->last_end_off && PFN_DOWN(bdata->last_end_off) + 1 == sidx))
    start_off = ALIGN(bdata->last_end_off, align);
    
    -you can see that the condition is true, so it assigns start_off =
    ALIGN(bdata->last_end_off, align); (that is PAGE_SIZE) and allocates
    over already allocated block.
    
    With the patch it tries to continue at the end of previous allocation only
    if the previous allocation ended in the middle of the page.
    Signed-off-by: NMikulas Patocka <mpatocka@redhat.com>
    Acked-by: NJohannes Weiner <hannes@saeurebad.de>
    Cc: David Miller <davem@davemloft.net>
    Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
    627240aa
bootmem.c 17.2 KB