lkml.org 
[lkml]   [2016]   [Jan]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.2 36/70] mm/memory_hotplug.c: check for missing sections in test_pages_in_a_zone()
    3.2.76-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Andrew Banman <abanman@sgi.com>

    commit 5f0f2887f4de9508dcf438deab28f1de8070c271 upstream.

    test_pages_in_a_zone() does not account for the possibility of missing
    sections in the given pfn range. pfn_valid_within always returns 1 when
    CONFIG_HOLES_IN_ZONE is not set, allowing invalid pfns from missing
    sections to pass the test, leading to a kernel oops.

    Wrap an additional pfn loop with PAGES_PER_SECTION granularity to check
    for missing sections before proceeding into the zone-check code.

    This also prevents a crash from offlining memory devices with missing
    sections. Despite this, it may be a good idea to keep the related patch
    '[PATCH 3/3] drivers: memory: prohibit offlining of memory blocks with
    missing sections' because missing sections in a memory block may lead to
    other problems not covered by the scope of this fix.

    Signed-off-by: Andrew Banman <abanman@sgi.com>
    Acked-by: Alex Thorlton <athorlton@sgi.com>
    Cc: Russ Anderson <rja@sgi.com>
    Cc: Alex Thorlton <athorlton@sgi.com>
    Cc: Yinghai Lu <yinghai@kernel.org>
    Cc: Greg KH <greg@kroah.com>
    Cc: Seth Jennings <sjennings@variantweb.net>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    mm/memory_hotplug.c | 31 +++++++++++++++++++------------
    1 file changed, 19 insertions(+), 12 deletions(-)

    --- a/mm/memory_hotplug.c
    +++ b/mm/memory_hotplug.c
    @@ -716,23 +716,30 @@ int is_mem_section_removable(unsigned lo
    */
    static int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn)
    {
    - unsigned long pfn;
    + unsigned long pfn, sec_end_pfn;
    struct zone *zone = NULL;
    struct page *page;
    int i;
    - for (pfn = start_pfn;
    + for (pfn = start_pfn, sec_end_pfn = SECTION_ALIGN_UP(start_pfn);
    pfn < end_pfn;
    - pfn += MAX_ORDER_NR_PAGES) {
    - i = 0;
    - /* This is just a CONFIG_HOLES_IN_ZONE check.*/
    - while ((i < MAX_ORDER_NR_PAGES) && !pfn_valid_within(pfn + i))
    - i++;
    - if (i == MAX_ORDER_NR_PAGES)
    + pfn = sec_end_pfn + 1, sec_end_pfn += PAGES_PER_SECTION) {
    + /* Make sure the memory section is present first */
    + if (!present_section_nr(pfn_to_section_nr(pfn)))
    continue;
    - page = pfn_to_page(pfn + i);
    - if (zone && page_zone(page) != zone)
    - return 0;
    - zone = page_zone(page);
    + for (; pfn < sec_end_pfn && pfn < end_pfn;
    + pfn += MAX_ORDER_NR_PAGES) {
    + i = 0;
    + /* This is just a CONFIG_HOLES_IN_ZONE check.*/
    + while ((i < MAX_ORDER_NR_PAGES) &&
    + !pfn_valid_within(pfn + i))
    + i++;
    + if (i == MAX_ORDER_NR_PAGES)
    + continue;
    + page = pfn_to_page(pfn + i);
    + if (zone && page_zone(page) != zone)
    + return 0;
    + zone = page_zone(page);
    + }
    }
    return 1;
    }

    \
     
     \ /
      Last update: 2016-01-18 05:01    [W:5.167 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site