]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ublk: optimize UBLK_IO_UNREGISTER_IO_BUF on daemon task
authorCaleb Sander Mateos <csander@purestorage.com>
Fri, 20 Jun 2025 15:10:06 +0000 (09:10 -0600)
committerJens Axboe <axboe@kernel.dk>
Tue, 1 Jul 2025 02:13:42 +0000 (20:13 -0600)
ublk_io_release() performs an expensive atomic refcount decrement. This
atomic operation is unnecessary in the common case where the request's
buffer is registered and unregistered on the daemon task before handling
UBLK_IO_COMMIT_AND_FETCH_REQ for the I/O. So if ublk_io_release() is
called on the daemon task and task_registered_buffers is positive, just
decrement task_registered_buffers (nonatomically). ublk_sub_req_ref()
will apply this decrement when it atomically subtracts from io->ref.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20250620151008.3976463-13-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/ublk_drv.c

index e38d4fe5e8333cfbc5c00a6402945e48ad50f05a..c3c0601db4871834488a948703e186b7cf633111 100644 (file)
@@ -2030,7 +2030,14 @@ static void ublk_io_release(void *priv)
        struct ublk_queue *ubq = rq->mq_hctx->driver_data;
        struct ublk_io *io = &ubq->ios[rq->tag];
 
-       ublk_put_req_ref(ubq, io, rq);
+       /*
+        * task_registered_buffers may be 0 if buffers were registered off task
+        * but unregistered on task. Or after UBLK_IO_COMMIT_AND_FETCH_REQ.
+        */
+       if (current == io->task && io->task_registered_buffers)
+               io->task_registered_buffers--;
+       else
+               ublk_put_req_ref(ubq, io, rq);
 }
 
 static int ublk_register_io_buf(struct io_uring_cmd *cmd,