Commit 4017eb91 authored by Jens Axboe's avatar Jens Axboe

io_uring: make loop_rw_iter() use original user supplied pointers

We jump through a hoop for fixed buffers, where we first map these to
a bvec(), then kmap() the bvec to obtain the pointer we copy to/from.
This was always a bit ugly, and with the set_fs changes, it ends up
being practically problematic as well.

There's no need to jump through these hoops, just use the original user
pointers and length for the non iter based read/write.
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent c8fb20b5
...@@ -790,7 +790,7 @@ static const struct io_op_def io_op_defs[] = { ...@@ -790,7 +790,7 @@ static const struct io_op_def io_op_defs[] = {
.unbound_nonreg_file = 1, .unbound_nonreg_file = 1,
.pollin = 1, .pollin = 1,
.async_size = sizeof(struct io_async_rw), .async_size = sizeof(struct io_async_rw),
.work_flags = IO_WQ_WORK_BLKCG, .work_flags = IO_WQ_WORK_BLKCG | IO_WQ_WORK_MM,
}, },
[IORING_OP_WRITE_FIXED] = { [IORING_OP_WRITE_FIXED] = {
.needs_file = 1, .needs_file = 1,
...@@ -798,7 +798,8 @@ static const struct io_op_def io_op_defs[] = { ...@@ -798,7 +798,8 @@ static const struct io_op_def io_op_defs[] = {
.unbound_nonreg_file = 1, .unbound_nonreg_file = 1,
.pollout = 1, .pollout = 1,
.async_size = sizeof(struct io_async_rw), .async_size = sizeof(struct io_async_rw),
.work_flags = IO_WQ_WORK_BLKCG | IO_WQ_WORK_FSIZE, .work_flags = IO_WQ_WORK_BLKCG | IO_WQ_WORK_FSIZE |
IO_WQ_WORK_MM,
}, },
[IORING_OP_POLL_ADD] = { [IORING_OP_POLL_ADD] = {
.needs_file = 1, .needs_file = 1,
...@@ -3115,9 +3116,10 @@ static inline loff_t *io_kiocb_ppos(struct kiocb *kiocb) ...@@ -3115,9 +3116,10 @@ static inline loff_t *io_kiocb_ppos(struct kiocb *kiocb)
* For files that don't have ->read_iter() and ->write_iter(), handle them * For files that don't have ->read_iter() and ->write_iter(), handle them
* by looping over ->read() or ->write() manually. * by looping over ->read() or ->write() manually.
*/ */
static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb, static ssize_t loop_rw_iter(int rw, struct io_kiocb *req, struct iov_iter *iter)
struct iov_iter *iter)
{ {
struct kiocb *kiocb = &req->rw.kiocb;
struct file *file = req->file;
ssize_t ret = 0; ssize_t ret = 0;
/* /*
...@@ -3137,11 +3139,8 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb, ...@@ -3137,11 +3139,8 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb,
if (!iov_iter_is_bvec(iter)) { if (!iov_iter_is_bvec(iter)) {
iovec = iov_iter_iovec(iter); iovec = iov_iter_iovec(iter);
} else { } else {
/* fixed buffers import bvec */ iovec.iov_base = u64_to_user_ptr(req->rw.addr);
iovec.iov_base = kmap(iter->bvec->bv_page) iovec.iov_len = req->rw.len;
+ iter->iov_offset;
iovec.iov_len = min(iter->count,
iter->bvec->bv_len - iter->iov_offset);
} }
if (rw == READ) { if (rw == READ) {
...@@ -3152,9 +3151,6 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb, ...@@ -3152,9 +3151,6 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb,
iovec.iov_len, io_kiocb_ppos(kiocb)); iovec.iov_len, io_kiocb_ppos(kiocb));
} }
if (iov_iter_is_bvec(iter))
kunmap(iter->bvec->bv_page);
if (nr < 0) { if (nr < 0) {
if (!ret) if (!ret)
ret = nr; ret = nr;
...@@ -3163,6 +3159,8 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb, ...@@ -3163,6 +3159,8 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb,
ret += nr; ret += nr;
if (nr != iovec.iov_len) if (nr != iovec.iov_len)
break; break;
req->rw.len -= nr;
req->rw.addr += nr;
iov_iter_advance(iter, nr); iov_iter_advance(iter, nr);
} }
...@@ -3352,7 +3350,7 @@ static int io_iter_do_read(struct io_kiocb *req, struct iov_iter *iter) ...@@ -3352,7 +3350,7 @@ static int io_iter_do_read(struct io_kiocb *req, struct iov_iter *iter)
if (req->file->f_op->read_iter) if (req->file->f_op->read_iter)
return call_read_iter(req->file, &req->rw.kiocb, iter); return call_read_iter(req->file, &req->rw.kiocb, iter);
else if (req->file->f_op->read) else if (req->file->f_op->read)
return loop_rw_iter(READ, req->file, &req->rw.kiocb, iter); return loop_rw_iter(READ, req, iter);
else else
return -EINVAL; return -EINVAL;
} }
...@@ -3543,7 +3541,7 @@ static int io_write(struct io_kiocb *req, bool force_nonblock, ...@@ -3543,7 +3541,7 @@ static int io_write(struct io_kiocb *req, bool force_nonblock,
if (req->file->f_op->write_iter) if (req->file->f_op->write_iter)
ret2 = call_write_iter(req->file, kiocb, iter); ret2 = call_write_iter(req->file, kiocb, iter);
else if (req->file->f_op->write) else if (req->file->f_op->write)
ret2 = loop_rw_iter(WRITE, req->file, kiocb, iter); ret2 = loop_rw_iter(WRITE, req, iter);
else else
ret2 = -EINVAL; ret2 = -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment