ublk: don't call ublk_dispatch_req() for NEED_GET_DATA

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>
This commit is contained in:
Caleb Sander Mateos 2025-04-30 16:52:32 -06:00 committed by Jens Axboe
parent 2fcb88bdf2
commit 9810362a57

View 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 * so immediately pass UBLK_IO_RES_NEED_GET_DATA to ublksrv
* and notify it. * and notify it.
*/ */
if (!(io->flags & UBLK_IO_FLAG_NEED_GET_DATA)) { 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",
pr_devel("%s: need get data. qid %d tag %d io_flags %x\n", __func__, ubq->q_id, req->tag, io->flags);
__func__, ubq->q_id, req->tag, io->flags); ublk_complete_io_cmd(io, UBLK_IO_RES_NEED_GET_DATA,
ublk_complete_io_cmd(io, UBLK_IO_RES_NEED_GET_DATA, issue_flags);
issue_flags); return;
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);
} }
if (!ublk_start_io(ubq, req, io)) if (!ublk_start_io(ubq, req, io))
@ -2045,6 +2032,24 @@ static int ublk_commit_and_fetch(const struct ublk_queue *ubq,
return 0; 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, static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
unsigned int issue_flags, unsigned int issue_flags,
const struct ublksrv_io_cmd *ub_cmd) 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: case UBLK_IO_NEED_GET_DATA:
if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV)) if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
goto out; 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); req = blk_mq_tag_to_rq(ub->tag_set.tags[ub_cmd->q_id], tag);
ublk_dispatch_req(ubq, req, issue_flags); if (!ublk_get_data(ubq, io, req))
return -EIOCBQUEUED; return -EIOCBQUEUED;
return UBLK_IO_RES_OK;
default: default:
goto out; goto out;
} }