So any arch code which uses page_mapping_file() might get the wrong answer, this function will return NULL for a swap backed page which can be a shmem pages. But shmem pages can still be shared among multiple process (and possibly at different virtual addresses if mremap was use). Attached is a patch that changes page_mapping_file() to return the shmem mapping for swap backed shmem page. I have not tested it (no way for me to test all those architecture) and i spotted this while working on something else. So i hope someone can take a closer look. Cheers, Jérôme
>From 6c76b9f8baa87ff872f6be5a44805a74c1e07fea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Glisse?= <jglisse@xxxxxxxxxx> Date: Wed, 27 May 2020 20:18:59 -0400 Subject: [PATCH] mm: fix cache flush for shmem page that are swap backed. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This might be a shmem page that is in a sense a file that can be mapped multiple times in different processes at possibly different virtual addresses (fork + mremap). So return the shmem mapping that will allow any arch code to find all mappings of the page. Note that even if page is not anonymous then the page might have a NULL page->mapping field if it is being truncated, but then it is fine as each pte poiting to the page will be remove and cache flushing should be handled properly by that part of the code. Signed-off-by: Jérôme Glisse <jglisse@xxxxxxxxxx> Cc: "Huang, Ying" <ying.huang@xxxxxxxxx> Cc: Michal Hocko <mhocko@xxxxxxxx> Cc: Mel Gorman <mgorman@xxxxxxxxxxxxxxxxxxx> Cc: Russell King <linux@xxxxxxxxxxxxxxx> Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> Cc: Mike Rapoport <rppt@xxxxxxxxxxxxxxxxxx> Cc: "David S. Miller" <davem@xxxxxxxxxxxxx> Cc: "James E.J. Bottomley" <jejb@xxxxxxxxxxxxxxxx> --- mm/util.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/mm/util.c b/mm/util.c index 988d11e6c17c..ec8739ab0cc3 100644 --- a/mm/util.c +++ b/mm/util.c @@ -685,8 +685,24 @@ EXPORT_SYMBOL(page_mapping); */ struct address_space *page_mapping_file(struct page *page) { - if (unlikely(PageSwapCache(page))) + if (unlikely(PageSwapCache(page))) { + /* + * This might be a shmem page that is in a sense a file that + * can be mapped multiple times in different processes at + * possibly different virtual addresses (fork + mremap). So + * return the shmem mapping that will allow any arch code to + * find all mappings of the page. + * + * Note that even if page is not anonymous then the page might + * have a NULL page->mapping field if it is being truncated, + * but then it is fine as each pte poiting to the page will be + * remove and cache flushing should be handled properly by that + * part of the code. + */ + if (!PageAnon(page)) + return page->mapping; return NULL; + } return page_mapping(page); } -- 2.26.2