Revert "mm: shmem: don't truncate page if memory failure happens"

This reverts commit b9d02f1bdd98f38e6e5ecacc9786a8f58f3f8b2c.

The error handling of that patch was fundamentally broken, and it needs
to be entirely re-done.

For example, in shmem_write_begin() it would call shmem_getpage(), then
ignore the error return from that, and look at the page pointer contents
instead.

And in shmem_read_mapping_page_gfp(), the patch tested PageHWPoison() on
a page pointer that two lines earlier had potentially been set as an
error pointer.

These issues could be individually fixed, but when it has this many
issues, I'm just reverting it instead of waiting for fixes.

Link: https://lore.kernel.org/linux-mm/20211111084617.6746-1-ajaygargnsit@gmail.com/
Reported-by: Ajay Garg <ajaygargnsit@gmail.com>
Reported-by: Jens Axboe <axboe@kernel.dk>
Cc: Yang Shi <shy828301@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+6 -51
+3 -11
mm/memory-failure.c
··· 58 58 #include <linux/ratelimit.h> 59 59 #include <linux/page-isolation.h> 60 60 #include <linux/pagewalk.h> 61 - #include <linux/shmem_fs.h> 62 61 #include "internal.h" 63 62 #include "ras/ras_event.h" 64 63 ··· 867 868 { 868 869 int ret; 869 870 struct address_space *mapping; 870 - bool extra_pins; 871 871 872 872 delete_from_lru_cache(p); 873 873 ··· 896 898 } 897 899 898 900 /* 899 - * The shmem page is kept in page cache instead of truncating 900 - * so is expected to have an extra refcount after error-handling. 901 - */ 902 - extra_pins = shmem_mapping(mapping); 903 - 904 - /* 905 901 * Truncation is a bit tricky. Enable it per file system for now. 906 902 * 907 903 * Open: to take i_rwsem or not for this? Right now we don't. 908 904 */ 909 905 ret = truncate_error_page(p, page_to_pfn(p), mapping); 910 - if (has_extra_refcount(ps, p, extra_pins)) 911 - ret = MF_FAILED; 912 - 913 906 out: 914 907 unlock_page(p); 908 + 909 + if (has_extra_refcount(ps, p, false)) 910 + ret = MF_FAILED; 915 911 916 912 return ret; 917 913 }
+3 -35
mm/shmem.c
··· 2456 2456 struct inode *inode = mapping->host; 2457 2457 struct shmem_inode_info *info = SHMEM_I(inode); 2458 2458 pgoff_t index = pos >> PAGE_SHIFT; 2459 - int ret = 0; 2460 2459 2461 2460 /* i_rwsem is held by caller */ 2462 2461 if (unlikely(info->seals & (F_SEAL_GROW | ··· 2466 2467 return -EPERM; 2467 2468 } 2468 2469 2469 - ret = shmem_getpage(inode, index, pagep, SGP_WRITE); 2470 - 2471 - if (*pagep && PageHWPoison(*pagep)) { 2472 - unlock_page(*pagep); 2473 - put_page(*pagep); 2474 - ret = -EIO; 2475 - } 2476 - 2477 - return ret; 2470 + return shmem_getpage(inode, index, pagep, SGP_WRITE); 2478 2471 } 2479 2472 2480 2473 static int ··· 2553 2562 if (sgp == SGP_CACHE) 2554 2563 set_page_dirty(page); 2555 2564 unlock_page(page); 2556 - 2557 - if (PageHWPoison(page)) { 2558 - put_page(page); 2559 - error = -EIO; 2560 - break; 2561 - } 2562 2565 } 2563 2566 2564 2567 /* ··· 3092 3107 page = find_get_page(inode->i_mapping, 0); 3093 3108 if (!page) 3094 3109 return ERR_PTR(-ECHILD); 3095 - if (PageHWPoison(page) || 3096 - !PageUptodate(page)) { 3110 + if (!PageUptodate(page)) { 3097 3111 put_page(page); 3098 3112 return ERR_PTR(-ECHILD); 3099 3113 } ··· 3100 3116 error = shmem_getpage(inode, 0, &page, SGP_READ); 3101 3117 if (error) 3102 3118 return ERR_PTR(error); 3103 - if (page && PageHWPoison(page)) { 3104 - unlock_page(page); 3105 - put_page(page); 3106 - return ERR_PTR(-ECHILD); 3107 - } 3108 3119 unlock_page(page); 3109 3120 } 3110 3121 set_delayed_call(done, shmem_put_link, page); ··· 3750 3771 kmem_cache_destroy(shmem_inode_cachep); 3751 3772 } 3752 3773 3753 - /* Keep the page in page cache instead of truncating it */ 3754 - static int shmem_error_remove_page(struct address_space *mapping, 3755 - struct page *page) 3756 - { 3757 - return 0; 3758 - } 3759 - 3760 3774 const struct address_space_operations shmem_aops = { 3761 3775 .writepage = shmem_writepage, 3762 3776 .set_page_dirty = __set_page_dirty_no_writeback, ··· 3760 3788 #ifdef CONFIG_MIGRATION 3761 3789 .migratepage = migrate_page, 3762 3790 #endif 3763 - .error_remove_page = shmem_error_remove_page, 3791 + .error_remove_page = generic_error_remove_page, 3764 3792 }; 3765 3793 EXPORT_SYMBOL(shmem_aops); 3766 3794 ··· 4171 4199 page = ERR_PTR(error); 4172 4200 else 4173 4201 unlock_page(page); 4174 - 4175 - if (PageHWPoison(page)) 4176 - page = ERR_PTR(-EIO); 4177 - 4178 4202 return page; 4179 4203 #else 4180 4204 /*
-5
mm/userfaultfd.c
··· 232 232 goto out; 233 233 } 234 234 235 - if (PageHWPoison(page)) { 236 - ret = -EIO; 237 - goto out_release; 238 - } 239 - 240 235 ret = mfill_atomic_install_pte(dst_mm, dst_pmd, dst_vma, dst_addr, 241 236 page, false, wp_copy); 242 237 if (ret)