• Hugh Dickins's avatar
    tmpfs: fix race between umount and swapoff · 778dd893
    Hugh Dickins authored
    The use of igrab() in swapoff's shmem_unuse_inode() is just as vulnerable
    to umount as that in shmem_writepage().
    
    Fix this instance by extending the protection of shmem_swaplist_mutex
    right across shmem_unuse_inode(): while it's on the list, the inode cannot
    be evicted (and the filesystem cannot be unmounted) without
    shmem_evict_inode() taking that mutex to remove it from the list.
    
    But since shmem_writepage() might take that mutex, we should avoid making
    memory allocations or memcg charges while holding it: prepare them at the
    outer level in shmem_unuse().  When mem_cgroup_cache_charge() was
    originally placed, we didn't know until that point that the page from swap
    was actually a shmem page; but nowadays it's noted in the swap_map, so
    we're safe to charge upfront.  For the radix_tree, do as is done in
    shmem_getpage(): preload upfront, but don't pin to the cpu; so we make a
    habit of refreshing the node pool, but might dip into GFP_NOWAIT reserves
    on occasion if subsequently preempted.
    
    With the allocation and charge moved out from shmem_unuse_inode(),
    we can also hold index map and info->lock over from finding the entry.
    Signed-off-by: default avatarHugh Dickins <hughd@google.com>
    Cc: Konstantin Khlebnikov <khlebnikov@openvz.org>
    Cc: <stable@kernel.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    778dd893
shmem.c 72.3 KB