• Pavel Tatashin's avatar
    mm: split deferred_init_range into initializing and freeing parts · 80b1f41c
    Pavel Tatashin authored
    In deferred_init_range() we initialize struct pages, and also free them
    to buddy allocator.  We do it in separate loops, because buddy page is
    computed ahead, so we do not want to access a struct page that has not
    been initialized yet.
    
    There is still, however, a corner case where it is potentially possible
    to access uninitialized struct page: this is when buddy page is from the
    next memblock range.
    
    This patch fixes this problem by splitting deferred_init_range() into
    two functions: one to initialize struct pages, and another to free them.
    
    In addition, this patch brings the following improvements:
     - Get rid of __def_free() helper function. And simplifies loop logic by
       adding a new pfn validity check function: deferred_pfn_valid().
     - Reduces number of variables that we track. So, there is a higher
       chance that we will avoid using stack to store/load variables inside
       hot loops.
     - Enables future multi-threading of these functions: do initialization
       in multiple threads, wait for all threads to finish, do freeing part
       in multithreading.
    
    Tested on x86 with 1T of memory to make sure no regressions are
    introduced.
    
    [akpm@linux-foundation.org: fix spello in comment]
    Link: http://lkml.kernel.org/r/20171107150446.32055-2-pasha.tatashin@oracle.comSigned-off-by: default avatarPavel Tatashin <pasha.tatashin@oracle.com>
    Acked-by: default avatarMichal Hocko <mhocko@suse.com>
    Cc: Steven Sistare <steven.sistare@oracle.com>
    Cc: Daniel Jordan <daniel.m.jordan@oracle.com>
    Cc: Mel Gorman <mgorman@techsingularity.net>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    80b1f41c
page_alloc.c 215 KB