Whamcloud - gitweb
LU-16579 llite: fix the wrong beyond read end calculation 65/50065/5
authorQian Yingjin <qian@ddn.com>
Mon, 20 Feb 2023 03:11:54 +0000 (22:11 -0500)
committerOleg Drokin <green@whamcloud.com>
Tue, 21 Mar 2023 23:10:42 +0000 (23:10 +0000)
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.

Fixes: 2f8f38effa ("LU-16412 llite: check read page past requested")
Signed-off-by: Qian Yingjin <qian@ddn.com>
Change-Id: I5bb7ab82e5e2de8b9bd911798fb8ae65fc7c91af
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/50065
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Patrick Farrell <pfarrell@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
lustre/llite/llite_internal.h
lustre/llite/rw.c
lustre/llite/vvp_io.c

index 89edc09..bf632d4 100644 (file)
@@ -1395,8 +1395,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 {
index 49f1688..bad0150 100644 (file)
@@ -1858,13 +1858,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;
 
@@ -1970,11 +1968,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:
@@ -2000,7 +1995,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);
index e19db59..7fa452e 100644 (file)
@@ -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);