IOC_MOVE_EXT returns 0 if the requested range is beyond i_size. In that
case we currently set io_u->resid = io_u->xfer_buflen, but
io_queue_event() interprets that as a zero read and fails with EIO. We
definitely do not want this behaviour so set io_u->error explicitly to
EINVAL so we fail with that instead when we are in this scenario.
len = io_u->xfer_buflen;
if (len != io_u->xfer_buflen) {
len = io_u->xfer_buflen;
if (len != io_u->xfer_buflen) {
- io_u->resid = io_u->xfer_buflen - len;
- io_u->error = 0;
+ if (len) {
+ io_u->resid = io_u->xfer_buflen - len;
+ io_u->error = 0;
+ } else {
+ /* access beyond i_size */
+ io_u->error = EINVAL;
+ }
}
if (ret)
io_u->error = errno;
}
if (ret)
io_u->error = errno;