• Mike Kravetz's avatar
    mm/page_isolation.c: make start_isolate_page_range() fail if already isolated · 2c7452a0
    Mike Kravetz authored
    start_isolate_page_range() is used to set the migrate type of a set of
    pageblocks to MIGRATE_ISOLATE while attempting to start a migration
    operation.  It assumes that only one thread is calling it for the
    specified range.  This routine is used by CMA, memory hotplug and
    gigantic huge pages.  Each of these users synchronize access to the
    range within their subsystem.  However, two subsystems (CMA and gigantic
    huge pages for example) could attempt operations on the same range.  If
    this happens, one thread may 'undo' the work another thread is doing.
    This can result in pageblocks being incorrectly left marked as
    MIGRATE_ISOLATE and therefore not available for page allocation.
    
    What is ideally needed is a way to synchronize access to a set of
    pageblocks that are undergoing isolation and migration.  The only thing
    we know about these pageblocks is that they are all in the same zone.  A
    per-node mutex is too coarse as we want to allow multiple operations on
    different ranges within the same zone concurrently.  Instead, we will
    use the migration type of the pageblocks themselves as a form of
    synchronization.
    
    start_isolate_page_range sets the migration type on a set of page-
    blocks going in order from the one associated with the smallest pfn to
    the largest pfn.  The zone lock is acquired to check and set the
    migration type.  When going through the list of pageblocks check if
    MIGRATE_ISOLATE is already set.  If so, this indicates another thread is
    working on this pageblock.  We know exactly which pageblocks we set, so
    clean up by undo those and return -EBUSY.
    
    This allows start_isolate_page_range to serve as a synchronization
    mechanism and will allow for more general use of callers making use of
    these interfaces.  Update comments in alloc_contig_range to reflect this
    new functionality.
    
    Each CPU holds the associated zone lock to modify or examine the
    migration type of a pageblock.  And, it will only examine/update a
    single pageblock per lock acquire/release cycle.
    
    Link: http://lkml.kernel.org/r/20180309224731.16978-1-mike.kravetz@oracle.comSigned-off-by: 's avatarMike Kravetz <mike.kravetz@oracle.com>
    Reviewed-by: 's avatarAndrew Morton <akpm@linux-foundation.org>
    Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
    Cc: Luiz Capitulino <lcapitulino@redhat.com>
    Cc: Michal Nazarewicz <mina86@mina86.com>
    Cc: Michal Hocko <mhocko@kernel.org>
    Cc: Vlastimil Babka <vbabka@suse.cz>
    Cc: Mel Gorman <mgorman@techsingularity.net>
    Cc: Johannes Weiner <hannes@cmpxchg.org>
    Signed-off-by: 's avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: 's avatarLinus Torvalds <torvalds@linux-foundation.org>
    2c7452a0