• Zach O'Keefe's avatar
    mm/MADV_COLLAPSE: don't expand collapse when vm_end is past requested end · 52dc0310
    Zach O'Keefe authored
    MADV_COLLAPSE acts on one hugepage-aligned/sized region at a time, until
    it has collapsed all eligible memory contained within the bounds supplied
    by the user.
    
    At the top of each hugepage iteration we (re)lock mmap_lock and
    (re)validate the VMA for eligibility and update variables that might have
    changed while mmap_lock was dropped.  One thing that might occur is that
    the VMA could be resized, and as such, we refetch vma->vm_end to make sure
    we don't collapse past the end of the VMA's new end.
    
    However, it's possible that when refetching vma->vm_end that we expand the
    region acted on by MADV_COLLAPSE if vma->vm_end is greater than size+len
    supplied by the user.
    
    The consequence here is that we may attempt to collapse more memory than
    requested, possibly yielding either "too much success" or "false failure"
    user-visible results.  An example of the former is if we MADV_COLLAPSE the
    first 4MiB of a 2TiB mmap()'d file, the incorrect refetch would cause the
    operation to block for much longer than anticipated as we attempt to
    collapse the entire TiB region.  An example of the latter is that applying
    MADV_COLLPSE to a 4MiB file mapped to the start of a 6MiB VMA will
    successfully collapse the first 4MiB, then incorrectly attempt to collapse
    the last hugepage-aligned/sized region -- fail (since readahead/page cache
    lookup will fail) -- and report a failure to the user.
    
    I don't believe there is a kernel stability concern here as we always
    (re)validate the VMA / region accordingly.  Also as Hugh mentions, the
    user-visible effects are: we try to collapse more memory than requested
    by the user, and/or failing an operation that should have otherwise
    succeeded.  An example is trying to collapse a 4MiB file contained
    within a 12MiB VMA.
    
    Don't expand the acted-on region when refetching vma->vm_end.
    
    Link: https://lkml.kernel.org/r/20221224082035.3197140-1-zokeefe@google.com
    Fixes: 4d24de94 ("mm: MADV_COLLAPSE: refetch vm_end after reacquiring mmap_lock")
    Signed-off-by: default avatarZach O'Keefe <zokeefe@google.com>
    Reported-by: default avatarHugh Dickins <hughd@google.com>
    Cc: Yang Shi <shy828301@gmail.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    52dc0310
khugepaged.c 70.2 KB