• Hugh Dickins's avatar
    mm: try_to_unuse check removing right swap · 68bdc8d6
    Hugh Dickins authored
    There's a possible race in try_to_unuse() which Nick Piggin led me to two
    years ago.  Where it does lock_page() after read_swap_cache_async(), what
    if another task removed that page from swapcache just before we locked it?
    
    It would sail though the (*swap_map > 1) tests doing nothing (because it
    could not have been removed from swapcache before its swap references were
    gone), until it reaches the delete_from_swap_cache(page) near the bottom.
    
    Now imagine that this page has been allocated to swap on a different swap
    area while we dropped page lock (perhaps at the top, perhaps in unuse_mm):
    we could wrongly remove from swap cache before the page has been written
    to swap, so a subsequent do_swap_page() would read in stale data from
    swap.
    
    I think this case could not happen before: remove_exclusive_swap_page()
    refused while page count was raised.  But now with reuse_swap_page() and
    try_to_free_swap() removing from swap cache without minding page count, I
    think it could happen - the previous patch argued that it was safe because
    try_to_unuse() already ignored page count, but overlooked that it might be
    breaking the assumptions in try_to_unuse() itself.
    Signed-off-by: default avatarHugh Dickins <hugh@veritas.com>
    Cc: Lee Schermerhorn <lee.schermerhorn@hp.com>
    Cc: Rik van Riel <riel@redhat.com>
    Cc: Nick Piggin <nickpiggin@yahoo.com.au>
    Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
    Cc: Robin Holt <holt@sgi.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    68bdc8d6
swapfile.c 45.4 KB