• Gang Li's avatar
    shmem: fix a race between shmem_unused_huge_shrink and shmem_evict_inode · 62c9827c
    Gang Li authored
    Fix a data race in commit 779750d2 ("shmem: split huge pages beyond
    i_size under memory pressure").
    
    Here are call traces causing race:
    
       Call Trace 1:
         shmem_unused_huge_shrink+0x3ae/0x410
         ? __list_lru_walk_one.isra.5+0x33/0x160
         super_cache_scan+0x17c/0x190
         shrink_slab.part.55+0x1ef/0x3f0
         shrink_node+0x10e/0x330
         kswapd+0x380/0x740
         kthread+0xfc/0x130
         ? mem_cgroup_shrink_node+0x170/0x170
         ? kthread_create_on_node+0x70/0x70
         ret_from_fork+0x1f/0x30
    
       Call Trace 2:
         shmem_evict_inode+0xd8/0x190
         evict+0xbe/0x1c0
         do_unlinkat+0x137/0x330
         do_syscall_64+0x76/0x120
         entry_SYSCALL_64_after_hwframe+0x3d/0xa2
    
    A simple explanation:
    
    Image there are 3 items in the local list (@list).  In the first
    traversal, A is not deleted from @list.
    
      1)    A->B->C
            ^
            |
            pos (leave)
    
    In the second traversal, B is deleted from @list.  Concurrently, A is
    deleted from @list through shmem_evict_inode() since last reference
    counter of inode is dropped by other thread.  Then the @list is corrupted.
    
      2)    A->B->C
            ^  ^
            |  |
         evict pos (drop)
    
    We should make sure the inode is either on the global list or deleted from
    any local list before iput().
    
    Fixed by moving inodes back to global list before we put them.
    
    [akpm@linux-foundation.org: coding style fixes]
    
    Link: https://lkml.kernel.org/r/20211125064502.99983-1-ligang.bdlg@bytedance.com
    Fixes: 779750d2 ("shmem: split huge pages beyond i_size under memory pressure")
    Signed-off-by: default avatarGang Li <ligang.bdlg@bytedance.com>
    Reviewed-by: default avatarMuchun Song <songmuchun@bytedance.com>
    Acked-by: default avatarKirill A. Shutemov <kirill.shutemov@linux.intel.com>
    Cc: Hugh Dickins <hughd@google.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    62c9827c
shmem.c 108 KB