]> git.proxmox.com Git - pve-kernel.git/blame - patches/kernel/0022-mm-shmem-do-not-wait-for-lock_page-in-shmem_unused_h.patch
rebase patches on top of Ubuntu-4.13.0-43.48
[pve-kernel.git] / patches / kernel / 0022-mm-shmem-do-not-wait-for-lock_page-in-shmem_unused_h.patch
CommitLineData
e866cbac
FG
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
3Date: Fri, 23 Mar 2018 09:19:21 +0100
4Subject: [PATCH] mm/shmem: do not wait for lock_page() in
5 shmem_unused_huge_shrink()
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10shmem_unused_huge_shrink() gets called from reclaim path. Waiting for
11page lock may lead to deadlock there.
12
13There was a bug report that may be attributed to this:
14
15http://lkml.kernel.org/r/alpine.LRH.2.11.1801242349220.30642@mail.ewheeler.net
16
17Replace lock_page() with trylock_page() and skip the page if we failed to
18lock it. We will get to the page on the next scan.
19
20We can test for the PageTransHuge() outside the page lock as we only need
21protection against splitting the page under us. Holding pin oni the page
22is enough for this.
23
24Link: http://lkml.kernel.org/r/20180316210830.43738-1-kirill.shutemov@linux.intel.com
25Fixes: 779750d20b93 ("shmem: split huge pages beyond i_size under memory pressure")
26Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
27Reported-by: Eric Wheeler <linux-mm@lists.ewheeler.net>
28Acked-by: Michal Hocko <mhocko@suse.com>
29Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
30Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
31Cc: Hugh Dickins <hughd@google.com>
32Cc: <stable@vger.kernel.org> [4.8+]
33Signed-off-by: Andrew Morton <>
34(cherry-picked from https://git.kernel.org/pub/scm/linux/kernel/git/mhocko/mm.git/commit/?h=since-4.15&id=73eccc61c701ee7b4223aea2079542a712feeea7)
35Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
36---
37 mm/shmem.c | 31 ++++++++++++++++++++-----------
38 1 file changed, 20 insertions(+), 11 deletions(-)
39
40diff --git a/mm/shmem.c b/mm/shmem.c
41index 859e4c224b80..2aae929eb90b 100644
42--- a/mm/shmem.c
43+++ b/mm/shmem.c
44@@ -483,36 +483,45 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
45 info = list_entry(pos, struct shmem_inode_info, shrinklist);
46 inode = &info->vfs_inode;
47
48- if (nr_to_split && split >= nr_to_split) {
49- iput(inode);
50- continue;
51- }
52+ if (nr_to_split && split >= nr_to_split)
53+ goto leave;
54
55- page = find_lock_page(inode->i_mapping,
56+ page = find_get_page(inode->i_mapping,
57 (inode->i_size & HPAGE_PMD_MASK) >> PAGE_SHIFT);
58 if (!page)
59 goto drop;
60
61+ /* No huge page at the end of the file: nothing to split */
62 if (!PageTransHuge(page)) {
63- unlock_page(page);
64 put_page(page);
65 goto drop;
66 }
67
68+ /*
69+ * Leave the inode on the list if we failed to lock
70+ * the page at this time.
71+ *
72+ * Waiting for the lock may lead to deadlock in the
73+ * reclaim path.
74+ */
75+ if (!trylock_page(page)) {
76+ put_page(page);
77+ goto leave;
78+ }
79+
80 ret = split_huge_page(page);
81 unlock_page(page);
82 put_page(page);
83
84- if (ret) {
85- /* split failed: leave it on the list */
86- iput(inode);
87- continue;
88- }
89+ /* If split failed leave the inode on the list */
90+ if (ret)
91+ goto leave;
92
93 split++;
94 drop:
95 list_del_init(&info->shrinklist);
96 removed++;
97+leave:
98 iput(inode);
99 }
100
101--
1022.14.2
103