ublk: factor out ublk_commit_and_fetch
authorUday Shankar <ushankar@purestorage.com>
Wed, 30 Apr 2025 22:52:26 +0000 (16:52 -0600)
committerJens Axboe <axboe@kernel.dk>
Fri, 2 May 2025 15:22:30 +0000 (09:22 -0600)
Move the logic for the UBLK_IO_COMMIT_AND_FETCH_REQ opcode into its own
function. This also allows us to mark ublk_queue pointers as const for
that operation, which can help prevent data races since we may allow
concurrent operation on one ublk_queue in the future. Also open code
ublk_commit_completion in ublk_commit_and_fetch to reduce the number of
parameters/avoid a redundant lookup.

[Restore __ublk_ch_uring_cmd() req variable used in commit d6aa0c178bf8
("ublk: call ublk_dispatch_req() for handling UBLK_U_IO_NEED_GET_DATA")]

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

index a183aa7648c36ddb385ddcbc8cb70ce3f5209523..7809ed585e1ca7ca88606ba279cf5d377a165d2a 100644 (file)
@@ -1589,30 +1589,6 @@ static int ublk_ch_mmap(struct file *filp, struct vm_area_struct *vma)
        return remap_pfn_range(vma, vma->vm_start, pfn, sz, vma->vm_page_prot);
 }
 
-static void ublk_commit_completion(struct ublk_device *ub,
-               const struct ublksrv_io_cmd *ub_cmd)
-{
-       u32 qid = ub_cmd->q_id, tag = ub_cmd->tag;
-       struct ublk_queue *ubq = ublk_get_queue(ub, qid);
-       struct ublk_io *io = &ubq->ios[tag];
-       struct request *req;
-
-       /* now this cmd slot is owned by nbd driver */
-       io->flags &= ~UBLK_IO_FLAG_OWNED_BY_SRV;
-       io->res = ub_cmd->result;
-
-       /* find the io request and complete */
-       req = blk_mq_tag_to_rq(ub->tag_set.tags[qid], tag);
-       if (WARN_ON_ONCE(unlikely(!req)))
-               return;
-
-       if (req_op(req) == REQ_OP_ZONE_APPEND)
-               req->__sector = ub_cmd->zone_append_lba;
-
-       if (likely(!blk_should_fake_timeout(req->q)))
-               ublk_put_req_ref(ubq, req);
-}
-
 static void __ublk_fail_req(struct ublk_queue *ubq, struct ublk_io *io,
                struct request *req)
 {
@@ -2021,6 +1997,47 @@ out:
        return ret;
 }
 
+static int ublk_commit_and_fetch(const struct ublk_queue *ubq,
+                                struct ublk_io *io, struct io_uring_cmd *cmd,
+                                const struct ublksrv_io_cmd *ub_cmd)
+{
+       struct blk_mq_tags *tags = ubq->dev->tag_set.tags[ub_cmd->q_id];
+       struct request *req = blk_mq_tag_to_rq(tags, ub_cmd->tag);
+
+       if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
+               return -EINVAL;
+
+       if (ublk_need_map_io(ubq)) {
+               /*
+                * COMMIT_AND_FETCH_REQ has to provide IO buffer if
+                * NEED GET DATA is not enabled or it is Read IO.
+                */
+               if (!ub_cmd->addr && (!ublk_need_get_data(ubq) ||
+                                       req_op(req) == REQ_OP_READ))
+                       return -EINVAL;
+       } else if (req_op(req) != REQ_OP_ZONE_APPEND && ub_cmd->addr) {
+               /*
+                * User copy requires addr to be unset when command is
+                * not zone append
+                */
+               return -EINVAL;
+       }
+
+       ublk_fill_io_cmd(io, cmd, ub_cmd->addr);
+
+       /* now this cmd slot is owned by ublk driver */
+       io->flags &= ~UBLK_IO_FLAG_OWNED_BY_SRV;
+       io->res = ub_cmd->result;
+
+       if (req_op(req) == REQ_OP_ZONE_APPEND)
+               req->__sector = ub_cmd->zone_append_lba;
+
+       if (likely(!blk_should_fake_timeout(req->q)))
+               ublk_put_req_ref(ubq, req);
+
+       return 0;
+}
+
 static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
                               unsigned int issue_flags,
                               const struct ublksrv_io_cmd *ub_cmd)
@@ -2079,30 +2096,9 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
                        goto out;
                break;
        case UBLK_IO_COMMIT_AND_FETCH_REQ:
-               req = blk_mq_tag_to_rq(ub->tag_set.tags[ub_cmd->q_id], tag);
-
-               if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
-                       goto out;
-
-               if (ublk_need_map_io(ubq)) {
-                       /*
-                        * COMMIT_AND_FETCH_REQ has to provide IO buffer if
-                        * NEED GET DATA is not enabled or it is Read IO.
-                        */
-                       if (!ub_cmd->addr && (!ublk_need_get_data(ubq) ||
-                                               req_op(req) == REQ_OP_READ))
-                               goto out;
-               } else if (req_op(req) != REQ_OP_ZONE_APPEND && ub_cmd->addr) {
-                       /*
-                        * User copy requires addr to be unset when command is
-                        * not zone append
-                        */
-                       ret = -EINVAL;
+               ret = ublk_commit_and_fetch(ubq, io, cmd, ub_cmd);
+               if (ret)
                        goto out;
-               }
-
-               ublk_fill_io_cmd(io, cmd, ub_cmd->addr);
-               ublk_commit_completion(ub, ub_cmd);
                break;
        case UBLK_IO_NEED_GET_DATA:
                if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))