]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ublk: don't call ublk_dispatch_req() for NEED_GET_DATA
authorCaleb Sander Mateos <csander@purestorage.com>
Wed, 30 Apr 2025 22:52:32 +0000 (16:52 -0600)
committerJens Axboe <axboe@kernel.dk>
Fri, 2 May 2025 15:22:30 +0000 (09:22 -0600)
ublk_dispatch_req() currently handles 3 different cases: incoming ublk
requests that don't need to wait for a data buffer, incoming requests
that do need to wait for a buffer, and resuming those requests once the
buffer is provided. But the call site that provides a data buffer
(UBLK_IO_NEED_GET_DATA) is separate from those for incoming requests.

So simplify the function by splitting the UBLK_IO_NEED_GET_DATA case
into its own function ublk_get_data(). This avoids several redundant
checks in the UBLK_IO_NEED_GET_DATA case, and streamlines the incoming
request cases.

Don't call ublk_fill_io_cmd() for UBLK_IO_NEED_GET_DATA, as it's no
longer necessary to set io->cmd or the UBLK_IO_FLAG_ACTIVE flag for
ublk_dispatch_req().

Since UBLK_IO_NEED_GET_DATA no longer relies on ublk_dispatch_req()
calling io_uring_cmd_done(), return the UBLK_IO_RES_OK status directly
from the ->uring_cmd() handler. If ublk_start_io() fails, don't complete
the UBLK_IO_NEED_GET_DATA command, matching the existing behavior.

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

index b4c64779c4fd4f591087f4588bff1efa2acd0ae7..483205a0dfe871baeaf6f5db6c5081c0e364a689 100644 (file)
@@ -1212,25 +1212,12 @@ static void ublk_dispatch_req(struct ublk_queue *ubq,
                 * so immediately pass UBLK_IO_RES_NEED_GET_DATA to ublksrv
                 * and notify it.
                 */
-               if (!(io->flags & UBLK_IO_FLAG_NEED_GET_DATA)) {
-                       io->flags |= UBLK_IO_FLAG_NEED_GET_DATA;
-                       pr_devel("%s: need get data. qid %d tag %d io_flags %x\n",
-                                       __func__, ubq->q_id, req->tag, io->flags);
-                       ublk_complete_io_cmd(io, UBLK_IO_RES_NEED_GET_DATA,
-                                            issue_flags);
-                       return;
-               }
-               /*
-                * We have handled UBLK_IO_NEED_GET_DATA command,
-                * so clear UBLK_IO_FLAG_NEED_GET_DATA now and just
-                * do the copy work.
-                */
-               io->flags &= ~UBLK_IO_FLAG_NEED_GET_DATA;
-               /* update iod->addr because ublksrv may have passed a new io buffer */
-               ublk_get_iod(ubq, req->tag)->addr = io->addr;
-               pr_devel("%s: update iod->addr: qid %d tag %d io_flags %x addr %llx\n",
-                               __func__, ubq->q_id, req->tag, io->flags,
-                               ublk_get_iod(ubq, req->tag)->addr);
+               io->flags |= UBLK_IO_FLAG_NEED_GET_DATA;
+               pr_devel("%s: need get data. qid %d tag %d io_flags %x\n",
+                               __func__, ubq->q_id, req->tag, io->flags);
+               ublk_complete_io_cmd(io, UBLK_IO_RES_NEED_GET_DATA,
+                                    issue_flags);
+               return;
        }
 
        if (!ublk_start_io(ubq, req, io))
@@ -2045,6 +2032,24 @@ static int ublk_commit_and_fetch(const struct ublk_queue *ubq,
        return 0;
 }
 
+static bool ublk_get_data(const struct ublk_queue *ubq, struct ublk_io *io,
+                         struct request *req)
+{
+       /*
+        * We have handled UBLK_IO_NEED_GET_DATA command,
+        * so clear UBLK_IO_FLAG_NEED_GET_DATA now and just
+        * do the copy work.
+        */
+       io->flags &= ~UBLK_IO_FLAG_NEED_GET_DATA;
+       /* update iod->addr because ublksrv may have passed a new io buffer */
+       ublk_get_iod(ubq, req->tag)->addr = io->addr;
+       pr_devel("%s: update iod->addr: qid %d tag %d io_flags %x addr %llx\n",
+                       __func__, ubq->q_id, req->tag, io->flags,
+                       ublk_get_iod(ubq, req->tag)->addr);
+
+       return ublk_start_io(ubq, req, io);
+}
+
 static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
                               unsigned int issue_flags,
                               const struct ublksrv_io_cmd *ub_cmd)
@@ -2110,10 +2115,12 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
        case UBLK_IO_NEED_GET_DATA:
                if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
                        goto out;
-               ublk_fill_io_cmd(io, cmd, ub_cmd->addr);
+               io->addr = ub_cmd->addr;
                req = blk_mq_tag_to_rq(ub->tag_set.tags[ub_cmd->q_id], tag);
-               ublk_dispatch_req(ubq, req, issue_flags);
-               return -EIOCBQUEUED;
+               if (!ublk_get_data(ubq, io, req))
+                       return -EIOCBQUEUED;
+
+               return UBLK_IO_RES_OK;
        default:
                goto out;
        }