lkml.org 
[lkml]   [2014]   [Jul]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH v3] memory hotplug: update the variables after memory removed
    Commit ea0854170c95 ("memory hotplug: fix a bug on /dev/mem
    for 64-bit kernels") added a fuction update_end_of_memory_vars()
    to update high_memory, max_pfn and max_low_pfn.

    Here we may access wrong memory via /dev/mem after memory remove
    without this patch.
    I modified the function and call it in arch_remove_memory() to update
    these variables too.

    Change v1->v2:
    - according to Dave Hansen and David Rientjes's suggestions modified
    update_end_of_memory_vars().
    change v2->v3:
    - remove the extra space before the function identifier of
    update_end_of_memory_vars().
    - remove the end_pfn and use start_pfn + nr_pages in the conditional.

    Signed-off-by: Zhang Zhen <zhenzhang.zhang@huawei.com>
    Acked-by: David Rientjes <rientjes@google.com>
    ---
    arch/x86/mm/init_64.c | 21 ++++++++++++---------
    1 file changed, 12 insertions(+), 9 deletions(-)

    diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
    index df1a992..d16368e 100644
    --- a/arch/x86/mm/init_64.c
    +++ b/arch/x86/mm/init_64.c
    @@ -673,15 +673,11 @@ void __init paging_init(void)
    * After memory hotplug the variables max_pfn, max_low_pfn and high_memory need
    * updating.
    */
    -static void update_end_of_memory_vars(u64 start, u64 size)
    +static void update_end_of_memory_vars(u64 end_pfn)
    {
    - unsigned long end_pfn = PFN_UP(start + size);
    -
    - if (end_pfn > max_pfn) {
    - max_pfn = end_pfn;
    - max_low_pfn = end_pfn;
    - high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
    - }
    + max_pfn = end_pfn;
    + max_low_pfn = end_pfn;
    + high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
    }

    /*
    @@ -694,6 +690,7 @@ int arch_add_memory(int nid, u64 start, u64 size)
    struct zone *zone = pgdat->node_zones + ZONE_NORMAL;
    unsigned long start_pfn = start >> PAGE_SHIFT;
    unsigned long nr_pages = size >> PAGE_SHIFT;
    + unsigned long end_pfn;
    int ret;

    init_memory_mapping(start, start + size);
    @@ -702,7 +699,9 @@ int arch_add_memory(int nid, u64 start, u64 size)
    WARN_ON_ONCE(ret);

    /* update max_pfn, max_low_pfn and high_memory */
    - update_end_of_memory_vars(start, size);
    + end_pfn = start_pfn + nr_pages;
    + if (end_pfn > max_pfn)
    + update_end_of_memory_vars(end_pfn);

    return ret;
    }
    @@ -1025,6 +1024,10 @@ int __ref arch_remove_memory(u64 start, u64 size)
    ret = __remove_pages(zone, start_pfn, nr_pages);
    WARN_ON_ONCE(ret);

    + /* update max_pfn, max_low_pfn and high_memory */
    + if ((max_pfn >= start_pfn) && (max_pfn < (start_pfn + nr_pages)))
    + update_end_of_memory_vars(start_pfn);
    +
    return ret;
    }
    #endif
    --
    1.8.1.2

    .








    \
     
     \ /
      Last update: 2014-07-29 16:01    [W:4.192 / U:3.080 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site