Skip to content

Commit 1065da2

Browse files
lxbszidryomov
authored andcommitted
ceph: stop copying to iter at EOF on sync reads
If EOF is encountered, ceph_sync_read() return value is adjusted down according to i_size, but the "to" iter is advanced by the actual number of bytes read. Then, when retrying, the remainder of the range may be skipped incorrectly. Ensure that the "to" iter is advanced only until EOF. [ idryomov: changelog ] Fixes: c3d8e0b ("ceph: return the real size read when it hits EOF") Reported-by: Frank Hsiao <[email protected]> Signed-off-by: Xiubo Li <[email protected]> Reviewed-by: Ilya Dryomov <[email protected]> Tested-by: Frank Hsiao <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]>
1 parent a8922f7 commit 1065da2

File tree

1 file changed

+13
-10
lines changed

1 file changed

+13
-10
lines changed

fs/ceph/file.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,7 +1138,12 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
11381138
}
11391139

11401140
idx = 0;
1141-
left = ret > 0 ? ret : 0;
1141+
if (ret <= 0)
1142+
left = 0;
1143+
else if (off + ret > i_size)
1144+
left = i_size - off;
1145+
else
1146+
left = ret;
11421147
while (left > 0) {
11431148
size_t plen, copied;
11441149

@@ -1167,15 +1172,13 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
11671172
}
11681173

11691174
if (ret > 0) {
1170-
if (off > *ki_pos) {
1171-
if (off >= i_size) {
1172-
*retry_op = CHECK_EOF;
1173-
ret = i_size - *ki_pos;
1174-
*ki_pos = i_size;
1175-
} else {
1176-
ret = off - *ki_pos;
1177-
*ki_pos = off;
1178-
}
1175+
if (off >= i_size) {
1176+
*retry_op = CHECK_EOF;
1177+
ret = i_size - *ki_pos;
1178+
*ki_pos = i_size;
1179+
} else {
1180+
ret = off - *ki_pos;
1181+
*ki_pos = off;
11791182
}
11801183

11811184
if (last_objver)

0 commit comments

Comments
 (0)