Skip to content

Commit 4017eb9

Browse files
committed
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: Jens Axboe <axboe@kernel.dk>
1 parent c8fb20b commit 4017eb9

1 file changed

Lines changed: 12 additions & 14 deletions

File tree

fs/io_uring.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -790,15 +790,16 @@ static const struct io_op_def io_op_defs[] = {
790790
.unbound_nonreg_file = 1,
791791
.pollin = 1,
792792
.async_size = sizeof(struct io_async_rw),
793-
.work_flags = IO_WQ_WORK_BLKCG,
793+
.work_flags = IO_WQ_WORK_BLKCG | IO_WQ_WORK_MM,
794794
},
795795
[IORING_OP_WRITE_FIXED] = {
796796
.needs_file = 1,
797797
.hash_reg_file = 1,
798798
.unbound_nonreg_file = 1,
799799
.pollout = 1,
800800
.async_size = sizeof(struct io_async_rw),
801-
.work_flags = IO_WQ_WORK_BLKCG | IO_WQ_WORK_FSIZE,
801+
.work_flags = IO_WQ_WORK_BLKCG | IO_WQ_WORK_FSIZE |
802+
IO_WQ_WORK_MM,
802803
},
803804
[IORING_OP_POLL_ADD] = {
804805
.needs_file = 1,
@@ -3115,9 +3116,10 @@ static inline loff_t *io_kiocb_ppos(struct kiocb *kiocb)
31153116
* For files that don't have ->read_iter() and ->write_iter(), handle them
31163117
* by looping over ->read() or ->write() manually.
31173118
*/
3118-
static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb,
3119-
struct iov_iter *iter)
3119+
static ssize_t loop_rw_iter(int rw, struct io_kiocb *req, struct iov_iter *iter)
31203120
{
3121+
struct kiocb *kiocb = &req->rw.kiocb;
3122+
struct file *file = req->file;
31213123
ssize_t ret = 0;
31223124

31233125
/*
@@ -3137,11 +3139,8 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb,
31373139
if (!iov_iter_is_bvec(iter)) {
31383140
iovec = iov_iter_iovec(iter);
31393141
} else {
3140-
/* fixed buffers import bvec */
3141-
iovec.iov_base = kmap(iter->bvec->bv_page)
3142-
+ iter->iov_offset;
3143-
iovec.iov_len = min(iter->count,
3144-
iter->bvec->bv_len - iter->iov_offset);
3142+
iovec.iov_base = u64_to_user_ptr(req->rw.addr);
3143+
iovec.iov_len = req->rw.len;
31453144
}
31463145

31473146
if (rw == READ) {
@@ -3152,9 +3151,6 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb,
31523151
iovec.iov_len, io_kiocb_ppos(kiocb));
31533152
}
31543153

3155-
if (iov_iter_is_bvec(iter))
3156-
kunmap(iter->bvec->bv_page);
3157-
31583154
if (nr < 0) {
31593155
if (!ret)
31603156
ret = nr;
@@ -3163,6 +3159,8 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb,
31633159
ret += nr;
31643160
if (nr != iovec.iov_len)
31653161
break;
3162+
req->rw.len -= nr;
3163+
req->rw.addr += nr;
31663164
iov_iter_advance(iter, nr);
31673165
}
31683166

@@ -3352,7 +3350,7 @@ static int io_iter_do_read(struct io_kiocb *req, struct iov_iter *iter)
33523350
if (req->file->f_op->read_iter)
33533351
return call_read_iter(req->file, &req->rw.kiocb, iter);
33543352
else if (req->file->f_op->read)
3355-
return loop_rw_iter(READ, req->file, &req->rw.kiocb, iter);
3353+
return loop_rw_iter(READ, req, iter);
33563354
else
33573355
return -EINVAL;
33583356
}
@@ -3543,7 +3541,7 @@ static int io_write(struct io_kiocb *req, bool force_nonblock,
35433541
if (req->file->f_op->write_iter)
35443542
ret2 = call_write_iter(req->file, kiocb, iter);
35453543
else if (req->file->f_op->write)
3546-
ret2 = loop_rw_iter(WRITE, req->file, kiocb, iter);
3544+
ret2 = loop_rw_iter(WRITE, req, iter);
35473545
else
35483546
ret2 = -EINVAL;
35493547

0 commit comments

Comments
 (0)