Commit 9810362a authored by Caleb Sander Mateos's avatar Caleb Sander Mateos Committed by Jens Axboe
Browse files

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: default avatarCaleb Sander Mateos <csander@purestorage.com>
Reviewed-by: default avatarMing Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20250430225234.2676781-8-csander@purestorage.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 2fcb88bd
Loading
Loading
Loading
Loading
+29 −22
Original line number Diff line number Diff line
@@ -1212,7 +1212,6 @@ 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);
@@ -1220,18 +1219,6 @@ static void ublk_dispatch_req(struct ublk_queue *ubq,
				     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);
	}

	if (!ublk_start_io(ubq, req, io))
		return;
@@ -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);
		if (!ublk_get_data(ubq, io, req))
			return -EIOCBQUEUED;

		return UBLK_IO_RES_OK;
	default:
		goto out;
	}