From 7d636316cdc88bf09ff409c78827e78eb58b1b8d Mon Sep 17 00:00:00 2001 From: Qian Yingjin Date: Sun, 19 Feb 2023 22:11:54 -0500 Subject: [PATCH] LU-16579 llite: fix the wrong beyond read end calculation During the test, we found a dead loop in the read path which retruns AOP_TRUNCATED_PAGE(0x8001) endless. The reason is that the calculation of the ending beyond offset is wrong: (iter->count + iocb->ki_pos). The ending beyond offset was supposed to be not changed during the read I/O loop for each page in buffered I/O mode. However, @iter->count is decreased with read bytes when finished the read of each page: @iter->count -= read_bytes. In this patch, we store the ending beyond page index in @lcc->lcc_end_index before call @generic_file_read_iter into a loop for each read page and solve this bug. Lustre-change: https://review.whamcloud.com/50065 Lustre-commit: ae356dc325877bd130ad94acc5f3610898de8a8a Fixes: 2f8f38effa ("LU-16412 llite: check read page past requested") Signed-off-by: Qian Yingjin Reviewed-by: Andreas Dilger Reviewed-by: Patrick Farrell Change-Id: I5bb7ab82e5e2de8b9bd911798fb8ae65fc7c91af Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/50068 Tested-by: jenkins Tested-by: Maloo --- lustre/llite/llite_internal.h | 3 +-- lustre/llite/rw.c | 15 +++++---------- lustre/llite/vvp_io.c | 6 ++---- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 86387fdf..2873534 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -1447,8 +1447,7 @@ struct ll_cl_context { struct cl_io *lcc_io; struct cl_page *lcc_page; enum lcc_type lcc_type; - struct kiocb *lcc_iocb; - struct iov_iter *lcc_iter; + pgoff_t lcc_end_index; }; struct ll_thread_info { diff --git a/lustre/llite/rw.c b/lustre/llite/rw.c index 0cf2db8..87e89d0 100644 --- a/lustre/llite/rw.c +++ b/lustre/llite/rw.c @@ -1850,13 +1850,11 @@ int ll_readpage(struct file *file, struct page *vmpage) struct inode *inode = file_inode(file); struct cl_object *clob = ll_i2info(inode)->lli_clob; struct ll_sb_info *sbi = ll_i2sbi(inode); - const struct lu_env *env = NULL; + const struct lu_env *env = NULL; struct cl_read_ahead ra = { 0 }; struct ll_cl_context *lcc; - struct cl_io *io = NULL; - struct iov_iter *iter; + struct cl_io *io = NULL; struct cl_page *page; - struct kiocb *iocb; int result; ENTRY; @@ -1963,11 +1961,8 @@ int ll_readpage(struct file *file, struct page *vmpage) } if (lcc && lcc->lcc_type != LCC_MMAP) { - iocb = lcc->lcc_iocb; - iter = lcc->lcc_iter; - - CDEBUG(D_VFSTRACE, "pgno:%ld, cnt:%ld, pos:%lld\n", - vmpage->index, iter->count, iocb->ki_pos); + CDEBUG(D_VFSTRACE, "pgno:%ld, beyond read end_index:%ld\n", + vmpage->index, lcc->lcc_end_index); /* * This handles a kernel bug introduced in kernel 5.12: @@ -1993,7 +1988,7 @@ int ll_readpage(struct file *file, struct page *vmpage) * This should never occur except in kernels with the bug * mentioned above. */ - if (cl_offset(clob, vmpage->index) >= iter->count + iocb->ki_pos) { + if (vmpage->index >= lcc->lcc_end_index) { result = cl_io_read_ahead(env, io, vmpage->index, &ra); if (result < 0 || vmpage->index > ra.cra_end_idx) { cl_read_ahead_release(env, &ra); diff --git a/lustre/llite/vvp_io.c b/lustre/llite/vvp_io.c index 7f99675..f0a85a6 100644 --- a/lustre/llite/vvp_io.c +++ b/lustre/llite/vvp_io.c @@ -889,10 +889,8 @@ static int vvp_io_read_start(const struct lu_env *env, iter = *vio->vui_iter; lcc = ll_cl_find(inode); - lcc->lcc_iter = &iter; - lcc->lcc_iocb = vio->vui_iocb; - CDEBUG(D_VFSTRACE, "cnt:%ld,iocb pos:%lld\n", lcc->lcc_iter->count, - lcc->lcc_iocb->ki_pos); + lcc->lcc_end_index = DIV_ROUND_UP(pos + iter.count, PAGE_SIZE); + CDEBUG(D_VFSTRACE, "count:%ld iocb pos:%lld\n", iter.count, pos); result = generic_file_read_iter(vio->vui_iocb, &iter); -- 1.8.3.1