mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-26 13:47:26 +00:00
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:
parent
2fcb88bdf2
commit
9810362a57
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user