Mel Gorman 91b69d
From ef355ceff0a14dae65451f9e0f5cbb9408c69977 Mon Sep 17 00:00:00 2001
Mel Gorman 91b69d
From: Linus Torvalds <torvalds@linux-foundation.org>
Mel Gorman 91b69d
Date: Sat, 13 Nov 2021 12:03:03 -0800
Mel Gorman 91b69d
Subject: [PATCH] Revert "mm: shmem: don't truncate page if memory failure
Mel Gorman 91b69d
 happens"
Mel Gorman 91b69d
Mel Gorman 91b69d
References: git fixes (mm/shmem)
Mel Gorman 91b69d
Patch-mainline: v5.16
Mel Gorman 91b69d
Git-commit: d0b51bfb23a21de771be3fd9c32ab072c2138dbd
Mel Gorman 91b69d
Mel Gorman 91b69d
This reverts commit b9d02f1bdd98f38e6e5ecacc9786a8f58f3f8b2c.
Mel Gorman 91b69d
Mel Gorman 91b69d
The error handling of that patch was fundamentally broken, and it needs
Mel Gorman 91b69d
to be entirely re-done.
Mel Gorman 91b69d
Mel Gorman 91b69d
For example, in shmem_write_begin() it would call shmem_getpage(), then
Mel Gorman 91b69d
ignore the error return from that, and look at the page pointer contents
Mel Gorman 91b69d
instead.
Mel Gorman 91b69d
Mel Gorman 91b69d
And in shmem_read_mapping_page_gfp(), the patch tested PageHWPoison() on
Mel Gorman 91b69d
a page pointer that two lines earlier had potentially been set as an
Mel Gorman 91b69d
error pointer.
Mel Gorman 91b69d
Mel Gorman 91b69d
These issues could be individually fixed, but when it has this many
Mel Gorman 91b69d
issues, I'm just reverting it instead of waiting for fixes.
Mel Gorman 91b69d
Mel Gorman 91b69d
Link: https://lore.kernel.org/linux-mm/20211111084617.6746-1-ajaygargnsit@gmail.com/
Mel Gorman 91b69d
Reported-by: Ajay Garg <ajaygargnsit@gmail.com>
Mel Gorman 91b69d
Reported-by: Jens Axboe <axboe@kernel.dk>
Mel Gorman 91b69d
Cc: Yang Shi <shy828301@gmail.com>
Mel Gorman 91b69d
Cc: Arnd Bergmann <arnd@arndb.de>
Mel Gorman 91b69d
Cc: Andrew Morton <akpm@linux-foundation.org>
Mel Gorman 91b69d
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Mel Gorman 91b69d
Signed-off-by: Mel Gorman <mgorman@suse.de>
Mel Gorman 91b69d
---
Mel Gorman 91b69d
 mm/memory-failure.c | 14 +++-----------
Mel Gorman 91b69d
 mm/shmem.c          | 38 +++-----------------------------------
Mel Gorman 91b69d
 mm/userfaultfd.c    |  5 -----
Mel Gorman 91b69d
 3 files changed, 6 insertions(+), 51 deletions(-)
Mel Gorman 91b69d
Mel Gorman 91b69d
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
Mel Gorman 91b69d
index 1db0d390175a..05ba4b23ff52 100644
Mel Gorman 91b69d
--- a/mm/memory-failure.c
Mel Gorman 91b69d
+++ b/mm/memory-failure.c
Mel Gorman 91b69d
@@ -57,7 +57,6 @@
Mel Gorman 91b69d
 #include <linux/ratelimit.h>
Mel Gorman 91b69d
 #include <linux/page-isolation.h>
Mel Gorman 91b69d
 #include <linux/pagewalk.h>
Mel Gorman 91b69d
-#include <linux/shmem_fs.h>
Mel Gorman 91b69d
 #include "internal.h"
Mel Gorman 91b69d
 #include "ras/ras_event.h"
Mel Gorman 91b69d
 
Mel Gorman 91b69d
@@ -868,7 +867,6 @@ static int me_pagecache_clean(struct page_state *ps, struct page *p)
Mel Gorman 91b69d
 {
Mel Gorman 91b69d
 	int ret;
Mel Gorman 91b69d
 	struct address_space *mapping;
Mel Gorman 91b69d
-	bool extra_pins;
Mel Gorman 91b69d
 
Mel Gorman 91b69d
 	delete_from_lru_cache(p);
Mel Gorman 91b69d
 
Mel Gorman 91b69d
@@ -897,24 +895,18 @@ static int me_pagecache_clean(struct page_state *ps, struct page *p)
Mel Gorman 91b69d
 		goto out;
Mel Gorman 91b69d
 	}
Mel Gorman 91b69d
 
Mel Gorman 91b69d
-	/*
Mel Gorman 91b69d
-	 * The shmem page is kept in page cache instead of truncating
Mel Gorman 91b69d
-	 * so is expected to have an extra refcount after error-handling.
Mel Gorman 91b69d
-	 */
Mel Gorman 91b69d
-	extra_pins = shmem_mapping(mapping);
Mel Gorman 91b69d
-
Mel Gorman 91b69d
 	/*
Mel Gorman 91b69d
 	 * Truncation is a bit tricky. Enable it per file system for now.
Mel Gorman 91b69d
 	 *
Mel Gorman 91b69d
 	 * Open: to take i_rwsem or not for this? Right now we don't.
Mel Gorman 91b69d
 	 */
Mel Gorman 91b69d
 	ret = truncate_error_page(p, page_to_pfn(p), mapping);
Mel Gorman 91b69d
-	if (has_extra_refcount(ps, p, extra_pins))
Mel Gorman 91b69d
-		ret = MF_FAILED;
Mel Gorman 91b69d
-
Mel Gorman 91b69d
 out:
Mel Gorman 91b69d
 	unlock_page(p);
Mel Gorman 91b69d
 
Mel Gorman 91b69d
+	if (has_extra_refcount(ps, p, false))
Mel Gorman 91b69d
+		ret = MF_FAILED;
Mel Gorman 91b69d
+
Mel Gorman 91b69d
 	return ret;
Mel Gorman 91b69d
 }
Mel Gorman 91b69d
 
Mel Gorman 91b69d
diff --git a/mm/shmem.c b/mm/shmem.c
Mel Gorman 91b69d
index 89062ce85db8..b5860f4a2738 100644
Mel Gorman 91b69d
--- a/mm/shmem.c
Mel Gorman 91b69d
+++ b/mm/shmem.c
Mel Gorman 91b69d
@@ -2456,7 +2456,6 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
Mel Gorman 91b69d
 	struct inode *inode = mapping->host;
Mel Gorman 91b69d
 	struct shmem_inode_info *info = SHMEM_I(inode);
Mel Gorman 91b69d
 	pgoff_t index = pos >> PAGE_SHIFT;
Mel Gorman 91b69d
-	int ret = 0;
Mel Gorman 91b69d
 
Mel Gorman 91b69d
 	/* i_rwsem is held by caller */
Mel Gorman 91b69d
 	if (unlikely(info->seals & (F_SEAL_GROW |
Mel Gorman 91b69d
@@ -2467,15 +2466,7 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
Mel Gorman 91b69d
 			return -EPERM;
Mel Gorman 91b69d
 	}
Mel Gorman 91b69d
 
Mel Gorman 91b69d
-	ret = shmem_getpage(inode, index, pagep, SGP_WRITE);
Mel Gorman 91b69d
-
Mel Gorman 91b69d
-	if (*pagep && PageHWPoison(*pagep)) {
Mel Gorman 91b69d
-		unlock_page(*pagep);
Mel Gorman 91b69d
-		put_page(*pagep);
Mel Gorman 91b69d
-		ret = -EIO;
Mel Gorman 91b69d
-	}
Mel Gorman 91b69d
-
Mel Gorman 91b69d
-	return ret;
Mel Gorman 91b69d
+	return shmem_getpage(inode, index, pagep, SGP_WRITE);
Mel Gorman 91b69d
 }
Mel Gorman 91b69d
 
Mel Gorman 91b69d
 static int
Mel Gorman 91b69d
@@ -2562,12 +2553,6 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
Mel Gorman 91b69d
 			if (sgp == SGP_CACHE)
Mel Gorman 91b69d
 				set_page_dirty(page);
Mel Gorman 91b69d
 			unlock_page(page);
Mel Gorman 91b69d
-
Mel Gorman 91b69d
-			if (PageHWPoison(page)) {
Mel Gorman 91b69d
-				put_page(page);
Mel Gorman 91b69d
-				error = -EIO;
Mel Gorman 91b69d
-				break;
Mel Gorman 91b69d
-			}
Mel Gorman 91b69d
 		}
Mel Gorman 91b69d
 
Mel Gorman 91b69d
 		/*
Mel Gorman 91b69d
@@ -3129,8 +3114,7 @@ static const char *shmem_get_link(struct dentry *dentry,
Mel Gorman 91b69d
 		page = find_get_page(inode->i_mapping, 0);
Mel Gorman 91b69d
 		if (!page)
Mel Gorman 91b69d
 			return ERR_PTR(-ECHILD);
Mel Gorman 91b69d
-		if (PageHWPoison(page) ||
Mel Gorman 91b69d
-		    !PageUptodate(page)) {
Mel Gorman 91b69d
+		if (!PageUptodate(page)) {
Mel Gorman 91b69d
 			put_page(page);
Mel Gorman 91b69d
 			return ERR_PTR(-ECHILD);
Mel Gorman 91b69d
 		}
Mel Gorman 91b69d
@@ -3138,11 +3122,6 @@ static const char *shmem_get_link(struct dentry *dentry,
Mel Gorman 91b69d
 		error = shmem_getpage(inode, 0, &page, SGP_READ);
Mel Gorman 91b69d
 		if (error)
Mel Gorman 91b69d
 			return ERR_PTR(error);
Mel Gorman 91b69d
-		if (page && PageHWPoison(page)) {
Mel Gorman 91b69d
-			unlock_page(page);
Mel Gorman 91b69d
-			put_page(page);
Mel Gorman 91b69d
-			return ERR_PTR(-ECHILD);
Mel Gorman 91b69d
-		}
Mel Gorman 91b69d
 		unlock_page(page);
Mel Gorman 91b69d
 	}
Mel Gorman 91b69d
 	set_delayed_call(done, shmem_put_link, page);
Mel Gorman 91b69d
@@ -3793,13 +3772,6 @@ static void shmem_destroy_inodecache(void)
Mel Gorman 91b69d
 	kmem_cache_destroy(shmem_inode_cachep);
Mel Gorman 91b69d
 }
Mel Gorman 91b69d
 
Mel Gorman 91b69d
-/* Keep the page in page cache instead of truncating it */
Mel Gorman 91b69d
-static int shmem_error_remove_page(struct address_space *mapping,
Mel Gorman 91b69d
-				   struct page *page)
Mel Gorman 91b69d
-{
Mel Gorman 91b69d
-	return 0;
Mel Gorman 91b69d
-}
Mel Gorman 91b69d
-
Mel Gorman 91b69d
 const struct address_space_operations shmem_aops = {
Mel Gorman 91b69d
 	.writepage	= shmem_writepage,
Mel Gorman 91b69d
 	.set_page_dirty	= __set_page_dirty_no_writeback,
Mel Gorman 91b69d
@@ -3810,7 +3782,7 @@ const struct address_space_operations shmem_aops = {
Mel Gorman 91b69d
 #ifdef CONFIG_MIGRATION
Mel Gorman 91b69d
 	.migratepage	= migrate_page,
Mel Gorman 91b69d
 #endif
Mel Gorman 91b69d
-	.error_remove_page = shmem_error_remove_page,
Mel Gorman 91b69d
+	.error_remove_page = generic_error_remove_page,
Mel Gorman 91b69d
 };
Mel Gorman 91b69d
 EXPORT_SYMBOL(shmem_aops);
Mel Gorman 91b69d
 
Mel Gorman 91b69d
@@ -4221,10 +4193,6 @@ struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
Mel Gorman 91b69d
 		page = ERR_PTR(error);
Mel Gorman 91b69d
 	else
Mel Gorman 91b69d
 		unlock_page(page);
Mel Gorman 91b69d
-
Mel Gorman 91b69d
-	if (PageHWPoison(page))
Mel Gorman 91b69d
-		page = ERR_PTR(-EIO);
Mel Gorman 91b69d
-
Mel Gorman 91b69d
 	return page;
Mel Gorman 91b69d
 #else
Mel Gorman 91b69d
 	/*
Mel Gorman 91b69d
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
Mel Gorman 91b69d
index 5dc996bafbba..0e2132834bc7 100644
Mel Gorman 91b69d
--- a/mm/userfaultfd.c
Mel Gorman 91b69d
+++ b/mm/userfaultfd.c
Mel Gorman 91b69d
@@ -233,11 +233,6 @@ static int mcontinue_atomic_pte(struct mm_struct *dst_mm,
Mel Gorman 91b69d
 		goto out;
Mel Gorman 91b69d
 	}
Mel Gorman 91b69d
 
Mel Gorman 91b69d
-	if (PageHWPoison(page)) {
Mel Gorman 91b69d
-		ret = -EIO;
Mel Gorman 91b69d
-		goto out_release;
Mel Gorman 91b69d
-	}
Mel Gorman 91b69d
-
Mel Gorman 91b69d
 	ret = mfill_atomic_install_pte(dst_mm, dst_pmd, dst_vma, dst_addr,
Mel Gorman 91b69d
 				       page, false, wp_copy);
Mel Gorman 91b69d
 	if (ret)