lkml.org 
[lkml]   [2012]   [Dec]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH] mm: Use aligned zone start for pfn_to_bitidx calculation
    Date
    The current calculation in pfn_to_bitidx assumes that
    (pfn - zone->zone_start_pfn) >> pageblock_order will return the
    same bit for all pfn in a pageblock. If zone_start_pfn is not
    aligned to pageblock_nr_pages, this may not always be correct.

    Consider the following with pageblock order = 10, zone start 2MB:

    pfn | pfn - zone start | (pfn - zone start) >> page block order
    ----------------------------------------------------------------
    0x26000 | 0x25e00 | 0x97
    0x26100 | 0x25f00 | 0x97
    0x26200 | 0x26000 | 0x98
    0x26300 | 0x26100 | 0x98

    This means that calling {get,set}_pageblock_migratetype on a single
    page will not set the migratetype for the full block. The correct
    fix is to round down zone_start_pfn for the bit index calculation.
    Rather than do this calculation everytime, store this precalcualted
    algined start in the zone structure to allow the actual start_pfn to
    be used elsewhere.

    Change-Id: I13e2f53f50db294f38ec86138c17c6fe29f0ee82
    Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
    ---
    include/linux/mmzone.h | 6 ++++++
    mm/page_alloc.c | 4 +++-
    2 files changed, 9 insertions(+), 1 deletions(-)

    diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
    index 08f74e6..0a5471b 100644
    --- a/include/linux/mmzone.h
    +++ b/include/linux/mmzone.h
    @@ -467,6 +467,12 @@ struct zone {
    struct pglist_data *zone_pgdat;
    /* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */
    unsigned long zone_start_pfn;
    + /*
    + * the starting pfn of the zone may not be aligned to the pageblock
    + * size which can throw off calculation of the pageblock flags.
    + * This is the precomputed aligned start of the zone
    + */
    + unsigned long aligned_start_pfn;

    /*
    * zone_start_pfn, spanned_pages and present_pages are all
    diff --git a/mm/page_alloc.c b/mm/page_alloc.c
    index c3142e8..d78e1d6 100644
    --- a/mm/page_alloc.c
    +++ b/mm/page_alloc.c
    @@ -3968,6 +3968,8 @@ __meminit int init_currently_empty_zone(struct zone *zone,
    pgdat->nr_zones = zone_idx(zone) + 1;

    zone->zone_start_pfn = zone_start_pfn;
    + zone->aligned_start_pfn = round_down(zone_start_pfn,
    + pageblock_nr_pages);

    mminit_dprintk(MMINIT_TRACE, "memmap_init",
    "Initialising map node %d zone %lu pfns %lu -> %lu\n",
    @@ -5424,7 +5426,7 @@ static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn)
    pfn &= (PAGES_PER_SECTION-1);
    return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS;
    #else
    - pfn = pfn - zone->zone_start_pfn;
    + pfn = pfn - zone->aligned_start_pfn;
    return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS;
    #endif /* CONFIG_SPARSEMEM */
    }
    --
    The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
    hosted by The Linux Foundation


    \
     
     \ /
      Last update: 2012-12-05 00:01    [W:2.525 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site