On Sat, 2021-10-30 at 13:16 +0800, xiubli@xxxxxxxxxx wrote: > From: Xiubo Li <xiubli@xxxxxxxxxx> > > Currently, if we end up reading more from the last object in the file > than the i_size indicates then we'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@xxxxxxxxxx> > --- > > Changed in V4: > - move the i_size_read() into the while loop and use the lastest i_size > read to do the check at the end of ceph_sync_read(). > > > fs/ceph/file.c | 13 ++++++++----- > 1 file changed, 8 insertions(+), 5 deletions(-) > > diff --git a/fs/ceph/file.c b/fs/ceph/file.c > index 91173d3aa161..6005b430f6f7 100644 > --- a/fs/ceph/file.c > +++ b/fs/ceph/file.c > @@ -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" : ""); > @@ -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; > @@ -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); Thanks, looks good. I dropped the two patches I had merged for this on Friday and merged this one instead. -- Jeff Layton <jlayton@xxxxxxxxxx>