diff options
author | Roman Penyaev <rpenyaev@suse.de> | 2019-03-25 20:09:24 +0100 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2019-03-25 13:13:21 -0600 |
commit | 9bf7933fc3f306bc4ce74ad734f690a71670178a (patch) | |
tree | 99a1c127e6ca7f99bee5b2595532f8c07b2ddb06 /fs/io_uring.c | |
parent | e6d1fa584e0dd9bfebaf345e9feea588cf75ead2 (diff) |
io_uring: offload write to async worker in case of -EAGAIN
In case of direct write -EAGAIN will be returned if page cache was
previously populated. To avoid immediate completion of a request
with -EAGAIN error write has to be offloaded to the async worker,
like io_read() does.
Signed-off-by: Roman Penyaev <rpenyaev@suse.de>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: linux-block@vger.kernel.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'fs/io_uring.c')
-rw-r--r-- | fs/io_uring.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c index 8f48d29abf76..bbdbd56cf2ac 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -1022,6 +1022,8 @@ static int io_write(struct io_kiocb *req, const struct sqe_submit *s, ret = rw_verify_area(WRITE, file, &kiocb->ki_pos, iov_count); if (!ret) { + ssize_t ret2; + /* * Open-code file_start_write here to grab freeze protection, * which will be released by another thread in @@ -1036,7 +1038,19 @@ static int io_write(struct io_kiocb *req, const struct sqe_submit *s, SB_FREEZE_WRITE); } kiocb->ki_flags |= IOCB_WRITE; - io_rw_done(kiocb, call_write_iter(file, kiocb, &iter)); + + ret2 = call_write_iter(file, kiocb, &iter); + if (!force_nonblock || ret2 != -EAGAIN) { + io_rw_done(kiocb, ret2); + } else { + /* + * If ->needs_lock is true, we're already in async + * context. + */ + if (!s->needs_lock) + io_async_list_note(WRITE, req, iov_count); + ret = -EAGAIN; + } } out_free: kfree(iovec); |