[pve-devel] applied: [PATCH pve-kernel-4.15 kernel] fix #1633: potential deadlock with shmem
Thomas Lamprecht
t.lamprecht at proxmox.com
Wed Mar 28 15:26:56 CEST 2018
applied this and the 4.13 one
On 3/28/18 3:14 PM, Fabian Grünbichler wrote:
> Signed-off-by: Fabian Grünbichler <f.gruenbichler at proxmox.com>
> ---
> ...-not-wait-for-lock_page-in-shmem_unused_h.patch | 103 +++++++++++++++++++++
> 1 file changed, 103 insertions(+)
> create mode 100644 patches/kernel/0007-mm-shmem-do-not-wait-for-lock_page-in-shmem_unused_h.patch
>
> diff --git a/patches/kernel/0007-mm-shmem-do-not-wait-for-lock_page-in-shmem_unused_h.patch b/patches/kernel/0007-mm-shmem-do-not-wait-for-lock_page-in-shmem_unused_h.patch
> new file mode 100644
> index 0000000..9d640ed
> --- /dev/null
> +++ b/patches/kernel/0007-mm-shmem-do-not-wait-for-lock_page-in-shmem_unused_h.patch
> @@ -0,0 +1,103 @@
> +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
> +From: "Kirill A. Shutemov" <kirill.shutemov at linux.intel.com>
> +Date: Fri, 23 Mar 2018 09:19:21 +0100
> +Subject: [PATCH] mm/shmem: do not wait for lock_page() in
> + shmem_unused_huge_shrink()
> +MIME-Version: 1.0
> +Content-Type: text/plain; charset=UTF-8
> +Content-Transfer-Encoding: 8bit
> +
> +shmem_unused_huge_shrink() gets called from reclaim path. Waiting for
> +page lock may lead to deadlock there.
> +
> +There was a bug report that may be attributed to this:
> +
> +http://lkml.kernel.org/r/alpine.LRH.2.11.1801242349220.30642@mail.ewheeler.net
> +
> +Replace lock_page() with trylock_page() and skip the page if we failed to
> +lock it. We will get to the page on the next scan.
> +
> +We can test for the PageTransHuge() outside the page lock as we only need
> +protection against splitting the page under us. Holding pin oni the page
> +is enough for this.
> +
> +Link: http://lkml.kernel.org/r/20180316210830.43738-1-kirill.shutemov@linux.intel.com
> +Fixes: 779750d20b93 ("shmem: split huge pages beyond i_size under memory pressure")
> +Signed-off-by: Kirill A. Shutemov <kirill.shutemov at linux.intel.com>
> +Reported-by: Eric Wheeler <linux-mm at lists.ewheeler.net>
> +Acked-by: Michal Hocko <mhocko at suse.com>
> +Reviewed-by: Andrew Morton <akpm at linux-foundation.org>
> +Cc: Tetsuo Handa <penguin-kernel at I-love.SAKURA.ne.jp>
> +Cc: Hugh Dickins <hughd at google.com>
> +Cc: <stable at vger.kernel.org> [4.8+]
> +Signed-off-by: Andrew Morton <>
> +(cherry-picked from https://git.kernel.org/pub/scm/linux/kernel/git/mhocko/mm.git/commit/?h=since-4.15&id=73eccc61c701ee7b4223aea2079542a712feeea7)
> +Signed-off-by: Fabian Grünbichler <f.gruenbichler at proxmox.com>
> +---
> + mm/shmem.c | 31 ++++++++++++++++++++-----------
> + 1 file changed, 20 insertions(+), 11 deletions(-)
> +
> +diff --git a/mm/shmem.c b/mm/shmem.c
> +index f6695c111086..800482fe6ed6 100644
> +--- a/mm/shmem.c
> ++++ b/mm/shmem.c
> +@@ -497,36 +497,45 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
> + info = list_entry(pos, struct shmem_inode_info, shrinklist);
> + inode = &info->vfs_inode;
> +
> +- if (nr_to_split && split >= nr_to_split) {
> +- iput(inode);
> +- continue;
> +- }
> ++ if (nr_to_split && split >= nr_to_split)
> ++ goto leave;
> +
> +- page = find_lock_page(inode->i_mapping,
> ++ page = find_get_page(inode->i_mapping,
> + (inode->i_size & HPAGE_PMD_MASK) >> PAGE_SHIFT);
> + if (!page)
> + goto drop;
> +
> ++ /* No huge page at the end of the file: nothing to split */
> + if (!PageTransHuge(page)) {
> +- unlock_page(page);
> + put_page(page);
> + goto drop;
> + }
> +
> ++ /*
> ++ * Leave the inode on the list if we failed to lock
> ++ * the page at this time.
> ++ *
> ++ * Waiting for the lock may lead to deadlock in the
> ++ * reclaim path.
> ++ */
> ++ if (!trylock_page(page)) {
> ++ put_page(page);
> ++ goto leave;
> ++ }
> ++
> + ret = split_huge_page(page);
> + unlock_page(page);
> + put_page(page);
> +
> +- if (ret) {
> +- /* split failed: leave it on the list */
> +- iput(inode);
> +- continue;
> +- }
> ++ /* If split failed leave the inode on the list */
> ++ if (ret)
> ++ goto leave;
> +
> + split++;
> + drop:
> + list_del_init(&info->shrinklist);
> + removed++;
> ++leave:
> + iput(inode);
> + }
> +
> +--
> +2.14.2
> +
>
More information about the pve-devel
mailing list