• Yosry Ahmed's avatar
    mm: zswap: handle incorrect attempts to load large folios · c63f210d
    Yosry Ahmed authored
    Zswap does not support storing or loading large folios.  Until proper
    support is added, attempts to load large folios from zswap are a bug.
    
    For example, if a swapin fault observes that contiguous PTEs are pointing
    to contiguous swap entries and tries to swap them in as a large folio,
    swap_read_folio() will pass in a large folio to zswap_load(), but
    zswap_load() will only effectively load the first page in the folio.  If
    the first page is not in zswap, the folio will be read from disk, even
    though other pages may be in zswap.
    
    In both cases, this will lead to silent data corruption.  Proper support
    needs to be added before large folio swapins and zswap can work together.
    
    Looking at callers of swap_read_folio(), it seems like they are either
    allocated from __read_swap_cache_async() or do_swap_page() in the
    SWP_SYNCHRONOUS_IO path.  Both of which allocate order-0 folios, so
    everything is fine for now.
    
    However, there is ongoing work to add to support large folio swapins [1]. 
    To make sure new development does not break zswap (or get broken by
    zswap), add minimal handling of incorrect loads of large folios to zswap. 
    First, move the call folio_mark_uptodate() inside zswap_load().
    
    If a large folio load is attempted, and zswap was ever enabled on the
    system, return 'true' without calling folio_mark_uptodate().  This will
    prevent the folio from being read from disk, and will emit an IO error
    because the folio is not uptodate (e.g.  do_swap_fault() will return
    VM_FAULT_SIGBUS).  It may not be reliable recovery in all cases, but it is
    better than nothing.
    
    This was tested by hacking the allocation in __read_swap_cache_async() to
    use order 2 and __GFP_COMP.
    
    In the future, to handle this correctly, the swapin code should:
    
    (a) Fall back to order-0 swapins if zswap was ever used on the
        machine, because compressed pages remain in zswap after it is
        disabled.
    
    (b) Add proper support to swapin large folios from zswap (fully or
        partially).
    
    Probably start with (a) then followup with (b).
    
    [1]https://lore.kernel.org/linux-mm/20240304081348.197341-6-21cnbao@gmail.com/
    
    Link: https://lkml.kernel.org/r/20240611024516.1375191-3-yosryahmed@google.comSigned-off-by: default avatarYosry Ahmed <yosryahmed@google.com>
    Acked-by: default avatarBarry Song <baohua@kernel.org>
    Cc: Barry Song <baohua@kernel.org>
    Cc: Chengming Zhou <chengming.zhou@linux.dev>
    Cc: Chris Li <chrisl@kernel.org>
    Cc: David Hildenbrand <david@redhat.com>
    Cc: Johannes Weiner <hannes@cmpxchg.org>
    Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
    Cc: Nhat Pham <nphamcs@gmail.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    c63f210d
zswap.c 49.1 KB