Skip to content

Commit bfe1255

Browse files
calebsanderaxboe
authored andcommitted
ublk: optimize ublk_user_copy() on daemon task
ublk user copy syscalls may be issued from any task, so they take a reference count on the struct ublk_io to check whether it is owned by the ublk server and prevent a concurrent UBLK_IO_COMMIT_AND_FETCH_REQ from completing the request. However, if the user copy syscall is issued on the io's daemon task, a concurrent UBLK_IO_COMMIT_AND_FETCH_REQ isn't possible, so the atomic reference count dance is unnecessary. Check for UBLK_IO_FLAG_OWNED_BY_SRV to ensure the request is dispatched to the sever and obtain the request from ublk_io's req field instead of looking it up on the tagset. Skip the reference count increment and decrement. Commit 8a8fe42 ("ublk: optimize UBLK_IO_REGISTER_IO_BUF on daemon task") made an analogous optimization for ublk zero copy buffer registration. Signed-off-by: Caleb Sander Mateos <csander@purestorage.com> Reviewed-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent b2503e9 commit bfe1255

1 file changed

Lines changed: 18 additions & 5 deletions

File tree

drivers/block/ublk_drv.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ struct ublk_io {
183183
* if user copy or zero copy are enabled:
184184
* - UBLK_REFCOUNT_INIT from dispatch to the server
185185
* until UBLK_IO_COMMIT_AND_FETCH_REQ
186-
* - 1 for each inflight ublk_ch_{read,write}_iter() call
186+
* - 1 for each inflight ublk_ch_{read,write}_iter() call not on task
187187
* - 1 for each io_uring registered buffer not registered on task
188188
* The I/O can only be completed once all references are dropped.
189189
* User copy and buffer registration operations are only permitted
@@ -2698,6 +2698,7 @@ ublk_user_copy(struct kiocb *iocb, struct iov_iter *iter, int dir)
26982698
struct ublk_io *io;
26992699
unsigned data_len;
27002700
bool is_integrity;
2701+
bool on_daemon;
27012702
size_t buf_off;
27022703
u16 tag, q_id;
27032704
ssize_t ret;
@@ -2727,9 +2728,20 @@ ublk_user_copy(struct kiocb *iocb, struct iov_iter *iter, int dir)
27272728
return -EINVAL;
27282729

27292730
io = &ubq->ios[tag];
2730-
req = __ublk_check_and_get_req(ub, q_id, tag, io);
2731-
if (!req)
2732-
return -EINVAL;
2731+
on_daemon = current == READ_ONCE(io->task);
2732+
if (on_daemon) {
2733+
/* On daemon, io can't be completed concurrently, so skip ref */
2734+
if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
2735+
return -EINVAL;
2736+
2737+
req = io->req;
2738+
if (!ublk_rq_has_data(req))
2739+
return -EINVAL;
2740+
} else {
2741+
req = __ublk_check_and_get_req(ub, q_id, tag, io);
2742+
if (!req)
2743+
return -EINVAL;
2744+
}
27332745

27342746
if (is_integrity) {
27352747
struct blk_integrity *bi = &req->q->limits.integrity;
@@ -2754,7 +2766,8 @@ ublk_user_copy(struct kiocb *iocb, struct iov_iter *iter, int dir)
27542766
ret = ublk_copy_user_pages(req, buf_off, iter, dir);
27552767

27562768
out:
2757-
ublk_put_req_ref(io, req);
2769+
if (!on_daemon)
2770+
ublk_put_req_ref(io, req);
27582771
return ret;
27592772
}
27602773

0 commit comments

Comments
 (0)