|
|
@@ -1,103 +0,0 @@
|
|
|
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
-From: "Kirill A. Shutemov" <[email protected]>
|
|
|
-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/[email protected]
|
|
|
-
|
|
|
-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/[email protected]
|
|
|
-Fixes: 779750d20b93 ("shmem: split huge pages beyond i_size under memory pressure")
|
|
|
-Signed-off-by: Kirill A. Shutemov <[email protected]>
|
|
|
-Reported-by: Eric Wheeler <[email protected]>
|
|
|
-Acked-by: Michal Hocko <[email protected]>
|
|
|
-Reviewed-by: Andrew Morton <[email protected]>
|
|
|
-Cc: Tetsuo Handa <[email protected]>
|
|
|
-Cc: Hugh Dickins <[email protected]>
|
|
|
-Cc: <[email protected]> [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 <[email protected]>
|
|
|
----
|
|
|
- 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
|
|
|
-
|