diff mbox series

[18/25] lustre: llite: Check for page deletion after fault

Message ID 20250130141115.950749-19-jsimmons@infradead.org (mailing list archive)
State New
Headers show
Series lustre: sync to OpenSFS branch April 30, 2023 | expand

Commit Message

James Simmons Jan. 30, 2025, 2:11 p.m. UTC
From: Patrick Farrell <pfarrell@whamcloud.com>

Before completing a page fault and returning to the kernel,
we lock the page and verify it has not been truncated.  But
we must also verify the page has not been deleted from
Lustre, or we can return a disconnected (ie, not tracked by
Lustre) page to the kernel.

We mark deleted pages !uptodate, but this doesn't matter
for faulted pages, because the kernel assumes they are
returned uptodate, and maps them in to the process address
space. Once mapped, the page state is not checked until
the page is unmapped.

But because the page is referenced by the mapping, it stays
in the page cache even though it's been disconnected from
Lustre.

Because the page is disconnected from Lustre, it will not
be found and cancelled on lock cancellation.  This can
result in stale data reads.

This is particularly an issue with releasepage (called from
drop_caches or under memory pressure), which can delete
pages separately from cancelling covering locks.

If releasepage is disabled, which is effectively what
"LU-14541 llite: Check vmpage in releasepage"
does, this is not an issue.  But disabling releasepage
causes other problems and is incorrect anyway.

Fixes: 9c78efe1a4 ("lustre: llite: Check vmpage in releasepage")
WC-bug-id: https://jira.whamcloud.com/browse/LU-14541
Lustre-commit: b3d2114e538cf95a7 ("LU-14541 llite: Check for page deletion after fault")
Signed-off-by: Patrick Farrell <pfarrell@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/49653
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Qian Yingjin <qian@ddn.com>
Reviewed-by: Zhenyu Xu <bobijam@hotmail.com>
Signed-off-by: James Simmons <jsimmons@infradead.org>
---
 fs/lustre/llite/llite_mmap.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/fs/lustre/llite/llite_mmap.c b/fs/lustre/llite/llite_mmap.c
index db069de1ef31..d6c1a6fd0794 100644
--- a/fs/lustre/llite/llite_mmap.c
+++ b/fs/lustre/llite/llite_mmap.c
@@ -418,15 +418,22 @@  static vm_fault_t ll_fault(struct vm_fault *vmf)
 	    !(result & (VM_FAULT_RETRY | VM_FAULT_ERROR | VM_FAULT_LOCKED))) {
 		struct page *vmpage = vmf->page;
 
-		/* check if this page has been truncated */
+		/* lock the page, then check if this page has been truncated
+		 * or deleted from Lustre and retry if so
+		 */
 		lock_page(vmpage);
-		if (unlikely(!vmpage->mapping)) { /* unlucky */
+		if (unlikely(vmpage->mapping == NULL) ||
+		    vmpage->private == 0) { /* unlucky */
 			unlock_page(vmpage);
 			put_page(vmpage);
 			vmf->page = NULL;
 
 			if (!printed && ++count > 16) {
-				CWARN("the page is under heavy contention, maybe your app(%s) needs revising :-)\n",
+				struct inode *inode = file_inode(vma->vm_file);
+
+				CWARN("%s: FID "DFID" under heavy mmap contention by '%s', consider revising IO pattern\n",
+				      ll_i2sbi(inode)->ll_fsname,
+				      PFID(&ll_i2info(inode)->lli_fid),
 				      current->comm);
 				printed = true;
 			}