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.
Fixes:
4468f6c9d9 ("LU-16025 llite: adjust read count as file got truncated")
Signed-off-by: Bobi Jam <bobijam@whamcloud.com>
Change-Id: Ib8b62c41bf65f8efec82dda53fcfbdb68ad08b38
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/53827
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Qian Yingjin <qian@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Patrick Farrell <patrick.farrell@oracle.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
#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
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;
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.
* 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;
}
}
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;
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)
break;
}
}
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
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"