[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