lkml.org 
[lkml]   [2021]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.13 385/800] mm/shmem: fix shmem_swapin() race with swapoff
    Date
    From: Miaohe Lin <linmiaohe@huawei.com>

    [ Upstream commit 2efa33fc7f6ec94a3a538c1a264273c889be2b36 ]

    When I was investigating the swap code, I found the below possible race
    window:

    CPU 1 CPU 2
    ----- -----
    shmem_swapin
    swap_cluster_readahead
    if (likely(si->flags & (SWP_BLKDEV | SWP_FS_OPS))) {
    swapoff
    ..
    si->swap_file = NULL;
    ..
    struct inode *inode = si->swap_file->f_mapping->host;[oops!]

    Close this race window by using get/put_swap_device() to guard against
    concurrent swapoff.

    Link: https://lkml.kernel.org/r/20210426123316.806267-5-linmiaohe@huawei.com
    Fixes: 8fd2e0b505d1 ("mm: swap: check if swap backing device is congested or not")
    Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
    Reviewed-by: "Huang, Ying" <ying.huang@intel.com>
    Cc: Dennis Zhou <dennis@kernel.org>
    Cc: Tim Chen <tim.c.chen@linux.intel.com>
    Cc: Hugh Dickins <hughd@google.com>
    Cc: Johannes Weiner <hannes@cmpxchg.org>
    Cc: Michal Hocko <mhocko@suse.com>
    Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
    Cc: Alex Shi <alexs@kernel.org>
    Cc: Matthew Wilcox <willy@infradead.org>
    Cc: Minchan Kim <minchan@kernel.org>
    Cc: Wei Yang <richard.weiyang@gmail.com>
    Cc: Yang Shi <shy828301@gmail.com>
    Cc: David Hildenbrand <david@redhat.com>
    Cc: Yu Zhao <yuzhao@google.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    mm/shmem.c | 14 +++++++++++++-
    1 file changed, 13 insertions(+), 1 deletion(-)

    diff --git a/mm/shmem.c b/mm/shmem.c
    index 5d46611cba8d..53f21016608e 100644
    --- a/mm/shmem.c
    +++ b/mm/shmem.c
    @@ -1696,7 +1696,8 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
    struct address_space *mapping = inode->i_mapping;
    struct shmem_inode_info *info = SHMEM_I(inode);
    struct mm_struct *charge_mm = vma ? vma->vm_mm : current->mm;
    - struct page *page;
    + struct swap_info_struct *si;
    + struct page *page = NULL;
    swp_entry_t swap;
    int error;

    @@ -1704,6 +1705,12 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
    swap = radix_to_swp_entry(*pagep);
    *pagep = NULL;

    + /* Prevent swapoff from happening to us. */
    + si = get_swap_device(swap);
    + if (!si) {
    + error = EINVAL;
    + goto failed;
    + }
    /* Look it up and read it in.. */
    page = lookup_swap_cache(swap, NULL, 0);
    if (!page) {
    @@ -1765,6 +1772,8 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
    swap_free(swap);

    *pagep = page;
    + if (si)
    + put_swap_device(si);
    return 0;
    failed:
    if (!shmem_confirm_swap(mapping, index, swap))
    @@ -1775,6 +1784,9 @@ unlock:
    put_page(page);
    }

    + if (si)
    + put_swap_device(si);
    +
    return error;
    }

    --
    2.30.2


    \
     
     \ /
      Last update: 2021-07-12 11:10    [W:3.197 / U:0.776 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site