From: Bobi Jam Date: Fri, 26 Jan 2024 10:14:36 +0000 (+0800) Subject: LU-17482 llite: short read could mess up next read offset X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=fbb319a60cc165c1ab14d50c81c35b5fd94f8dcb;p=fs%2Flustre-release.git LU-17482 llite: short read could mess up next read offset When read reaches EOF, it could read data from stale pagecache, but we need to restore the iocb->ki_pos so that next read could continue from the correct offset. Lustre-change: https://review.whamcloud.com/53827 Lustre-commit: TBD (from 4bec3a277c83932cfb5ba26e31336e1f4666460a) Fixes: 4468f6c9d9 ("LU-16025 llite: adjust read count as file got truncated") Signed-off-by: Bobi Jam Change-Id: Ib8b62c41bf65f8efec82dda53fcfbdb68ad08b38 Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/53828 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Patrick Farrell Reviewed-by: Andreas Dilger --- diff --git a/lustre/include/obd_support.h b/lustre/include/obd_support.h index b4a0e27..6f777b3 100644 --- a/lustre/include/obd_support.h +++ b/lustre/include/obd_support.h @@ -638,6 +638,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_LOV_COMP_PATTERN 0x1427 #define OBD_FAIL_LOV_INVALID_OSTIDX 0x1428 #define OBD_FAIL_LLITE_DELAY_TRUNCATE 0x1430 +#define OBD_FAIL_LLITE_READ_PAUSE 0x1431 #define OBD_FAIL_FID_INDIR 0x1501 #define OBD_FAIL_FID_INLMA 0x1502 diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 78074b7..e38d944 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -2114,6 +2114,7 @@ static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to) struct lu_env *env; struct vvp_io_args *args; struct file *file = iocb->ki_filp; + loff_t orig_ki_pos = iocb->ki_pos; ssize_t result; ssize_t rc2; __u16 refcheck; @@ -2141,6 +2142,8 @@ static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to) else if (result > 0) stale_data = true; + CFS_FAIL_TIMEOUT_ORSET(OBD_FAIL_LLITE_READ_PAUSE, CFS_FAIL_ONCE, + cfs_fail_val); /** * Currently when PCC read failed, we do not fall back to the * normal read path, just return the error. @@ -2181,6 +2184,7 @@ out: * we've reached EOF before the read, the data read are cached * stale data. */ + iocb->ki_pos = orig_ki_pos; iov_iter_truncate(to, 0); result = 0; } diff --git a/lustre/tests/multiop.c b/lustre/tests/multiop.c index 09ff6e1..cccd454 100644 --- a/lustre/tests/multiop.c +++ b/lustre/tests/multiop.c @@ -623,6 +623,9 @@ int main(int argc, char **argv) ~ALIGN_LEN); } while (len > 0) { + off_t start, off; + + start = lseek(fd, 0, SEEK_CUR); rc = read(fd, buf_align, len); if (rc == -1) { save_errno = errno; @@ -630,8 +633,9 @@ int main(int argc, char **argv) exit(save_errno); } if (rc < len) { - fprintf(stderr, "short read: %lld/%u\n", - rc, len); + off = lseek(fd, 0, SEEK_CUR); + fprintf(stderr, "short read: %ld ->+ %u -> %ld %lld\n", + start, len, off, rc); if (rc == 0) exit(ENODATA); } diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 23d25c7..1b2f971 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -22297,7 +22297,7 @@ test_250() { } run_test 250 "Write above 16T limit" -test_251() { +test_251a() { $LFS setstripe -c -1 -S 1048576 $DIR/$tfile #define OBD_FAIL_LLITE_LOST_LAYOUT 0x1407 @@ -22312,7 +22312,29 @@ test_251() { rm -f $DIR/$tfile } -run_test 251 "Handling short read and write correctly" +run_test 251a "Handling short read and write correctly" + +test_251b() { + dd if=/dev/zero of=$DIR/$tfile bs=1k count=4 || + error "write $tfile failed" + + sleep 2 && echo 12345 >> $DIR/$tfile & + + #define OBD_FAIL_LLITE_READ_PAUSE 0x1431 + $LCTL set_param fail_loc=0x1431 fail_val=5 + # seek to 4096, 2 seconds later, file size expand to 4102, and after + # 5 seconds, read 10 bytes, the short read should + # report: + # start ->+ read_len -> offset_after_read read_count + # short read: 4096 ->+ 10 -> 4096 0 + # not: + # short read: 4096 ->+ 10 -> 4102 0 + local off=$($MULTIOP $DIR/$tfile oO_RDONLY:z4096r10c 2>&1 | \ + awk '/short read/ { print $7 }') + (( off == 4096 )) || + error "short read should set offset at 4096, not $off" +} +run_test 251b "short read restore offset correctly" test_252() { remote_mds_nodsh && skip "remote MDS with nodsh"