Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp4123813pxb; Mon, 8 Feb 2021 08:29:57 -0800 (PST) X-Google-Smtp-Source: ABdhPJz4TAJoj5NOyBOKvxJSJNTLwBtwmmnD+wOLRTxxeuXI6i6GCuJIwvxr9voaC0eCyAzdzmko X-Received: by 2002:a17:906:a106:: with SMTP id t6mr18009277ejy.63.1612801797761; Mon, 08 Feb 2021 08:29:57 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1612801797; cv=none; d=google.com; s=arc-20160816; b=xaAiMDR7W0NdZm9hVJEc1pKYXKGKGA+eGTbc204oMPMAfH5Aix89DdhnsRXwzQxkkh B9kv+ajXxJdgd8SIzeEbfP99tqCRct09V5pNGk/hBwzFImBIp2QvM+KwDV5kPba72EGd KAqu+CSj97z/G0BJKlJdlpEeGp2lkY8eStjA6RAwQf6Y5ki/Xms2uXT/V0U6GibpqSDZ rL3nKVRUPzDog+6YwFepXuyY9wmTXSxoUL107yaMvT5wIgaOLFKNf2SzxfuVMgART7Mj nkqh+Y/elQsZb8ww9VGcQuHyLeC5l9WsfNGDmtzvtL+bpT4XKdyWa4woeY/zel1c4vmB g5Yw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=wJND90Yj0OfVwG5G8yONHvuGyHy2ZLuMxbjEqwqAUKI=; b=OKA49Wq3q8ec7kwqKe1fzFTuotu5WNs2BSN9fYK/2bjxvBKAv8AG5wI+VidcifF16X Qv2FHDDS9t6se8DvNxNt4r+t1SZ0Affeu9H2C3d3oErt+fefVGa2oi2lqaVgRx/P33yp KZjletvdxEFiXvcuMxfAHnAmLZws9FUlPF8lLYcgleJYaMtHwOhxhDJuDZbv01jztEJY WgSKXyR+XOHP9TE3ZjyPi47wbvsW2NXCHSkZARZ4xMupd2FP8pJRaOxt6Xur7oVjYSiF hpp031nE7gAfqtNy/UdMT1/OaKenuasLj+aGLzezsnu6WrN5BWUBjAElPoR2w7S86b42 wDtw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="F8/P1Qio"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id i8si4694290edg.104.2021.02.08.08.29.33; Mon, 08 Feb 2021 08:29:57 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="F8/P1Qio"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233380AbhBHQ0O (ORCPT + 99 others); Mon, 8 Feb 2021 11:26:14 -0500 Received: from mail.kernel.org ([198.145.29.99]:55766 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232701AbhBHPI5 (ORCPT ); Mon, 8 Feb 2021 10:08:57 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 65C4964EC8; Mon, 8 Feb 2021 15:06:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1612796804; bh=J+10Mpewm2xogp0pBcdLYmuNsNgvFS3yebqvDGPNhlA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=F8/P1Qio6Z811X6ffZrbR1B0CyO1DAejxyvA9/xauCMcDMcZPoyc8UuoZKILcO0cS xBPS2DeUbGOOxIPuSW0yBo769yaxwvaCE0hBcd/P5eyyPn5EgjLtuHxmwIWprhLqo7 gpgqqQ9B2fxqzxwU6kIHsTxEEu6psI62I+Fd8Ook= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Hugh Dickins , Sergey Senozhatsky , Andrea Arcangeli , Andrew Morton , Linus Torvalds Subject: [PATCH 4.14 25/30] mm: thp: fix MADV_REMOVE deadlock on shmem THP Date: Mon, 8 Feb 2021 16:01:11 +0100 Message-Id: <20210208145806.261891437@linuxfoundation.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210208145805.239714726@linuxfoundation.org> References: <20210208145805.239714726@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Hugh Dickins commit 1c2f67308af4c102b4e1e6cd6f69819ae59408e0 upstream. Sergey reported deadlock between kswapd correctly doing its usual lock_page(page) followed by down_read(page->mapping->i_mmap_rwsem), and madvise(MADV_REMOVE) on an madvise(MADV_HUGEPAGE) area doing down_write(page->mapping->i_mmap_rwsem) followed by lock_page(page). This happened when shmem_fallocate(punch hole)'s unmap_mapping_range() reaches zap_pmd_range()'s call to __split_huge_pmd(). The same deadlock could occur when partially truncating a mapped huge tmpfs file, or using fallocate(FALLOC_FL_PUNCH_HOLE) on it. __split_huge_pmd()'s page lock was added in 5.8, to make sure that any concurrent use of reuse_swap_page() (holding page lock) could not catch the anon THP's mapcounts and swapcounts while they were being split. Fortunately, reuse_swap_page() is never applied to a shmem or file THP (not even by khugepaged, which checks PageSwapCache before calling), and anonymous THPs are never created in shmem or file areas: so that __split_huge_pmd()'s page lock can only be necessary for anonymous THPs, on which there is no risk of deadlock with i_mmap_rwsem. Link: https://lkml.kernel.org/r/alpine.LSU.2.11.2101161409470.2022@eggly.anvils Fixes: c444eb564fb1 ("mm: thp: make the THP mapcount atomic against __split_huge_pmd_locked()") Signed-off-by: Hugh Dickins Reported-by: Sergey Senozhatsky Reviewed-by: Andrea Arcangeli Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/huge_memory.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2198,7 +2198,7 @@ void __split_huge_pmd(struct vm_area_str spinlock_t *ptl; struct mm_struct *mm = vma->vm_mm; unsigned long haddr = address & HPAGE_PMD_MASK; - bool was_locked = false; + bool do_unlock_page = false; pmd_t _pmd; mmu_notifier_invalidate_range_start(mm, haddr, haddr + HPAGE_PMD_SIZE); @@ -2211,7 +2211,6 @@ void __split_huge_pmd(struct vm_area_str VM_BUG_ON(freeze && !page); if (page) { VM_WARN_ON_ONCE(!PageLocked(page)); - was_locked = true; if (page != pmd_page(*pmd)) goto out; } @@ -2220,19 +2219,29 @@ repeat: if (pmd_trans_huge(*pmd)) { if (!page) { page = pmd_page(*pmd); - if (unlikely(!trylock_page(page))) { - get_page(page); - _pmd = *pmd; - spin_unlock(ptl); - lock_page(page); - spin_lock(ptl); - if (unlikely(!pmd_same(*pmd, _pmd))) { - unlock_page(page); + /* + * An anonymous page must be locked, to ensure that a + * concurrent reuse_swap_page() sees stable mapcount; + * but reuse_swap_page() is not used on shmem or file, + * and page lock must not be taken when zap_pmd_range() + * calls __split_huge_pmd() while i_mmap_lock is held. + */ + if (PageAnon(page)) { + if (unlikely(!trylock_page(page))) { + get_page(page); + _pmd = *pmd; + spin_unlock(ptl); + lock_page(page); + spin_lock(ptl); + if (unlikely(!pmd_same(*pmd, _pmd))) { + unlock_page(page); + put_page(page); + page = NULL; + goto repeat; + } put_page(page); - page = NULL; - goto repeat; } - put_page(page); + do_unlock_page = true; } } if (PageMlocked(page)) @@ -2242,7 +2251,7 @@ repeat: __split_huge_pmd_locked(vma, pmd, haddr, freeze); out: spin_unlock(ptl); - if (!was_locked && page) + if (do_unlock_page) unlock_page(page); mmu_notifier_invalidate_range_end(mm, haddr, haddr + HPAGE_PMD_SIZE); }