Skip to content

Commit

Permalink
ceph: return the real size read when it hits EOF
Browse files Browse the repository at this point in the history
Currently, if the sync read handler ends up reading more from the last
object in the file than the i_size indicates, then it'll end up
returning the wrong length. Ensure that we cap the returned length and
pos at the EOF.

Signed-off-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
  • Loading branch information
Xiubo Li authored and Ilya Dryomov committed Nov 8, 2021
1 parent 8cfc0c7 commit c3d8e0b
Showing 1 changed file with 8 additions and 5 deletions.
13 changes: 8 additions & 5 deletions fs/ceph/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *to,
ssize_t ret;
u64 off = iocb->ki_pos;
u64 len = iov_iter_count(to);
u64 i_size;

dout("sync_read on file %p %llu~%u %s\n", file, off, (unsigned)len,
(file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
Expand All @@ -870,7 +871,6 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *to,
struct page **pages;
int num_pages;
size_t page_off;
u64 i_size;
bool more;
int idx;
size_t left;
Expand Down Expand Up @@ -953,11 +953,14 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *to,
}

if (off > iocb->ki_pos) {
if (ret >= 0 &&
iov_iter_count(to) > 0 && off >= i_size_read(inode))
if (off >= i_size) {
*retry_op = CHECK_EOF;
ret = off - iocb->ki_pos;
iocb->ki_pos = off;
ret = i_size - iocb->ki_pos;
iocb->ki_pos = i_size;
} else {
ret = off - iocb->ki_pos;
iocb->ki_pos = off;
}
}

dout("sync_read result %zd retry_op %d\n", ret, *retry_op);
Expand Down

0 comments on commit c3d8e0b

Please sign in to comment.