Commit 0cb39afd authored by Uday Shankar's avatar Uday Shankar Committed by Jens Axboe
Browse files

ublk: factor out ublk_commit_and_fetch



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 d6aa0c17
("ublk: call ublk_dispatch_req() for handling UBLK_U_IO_NEED_GET_DATA")]

Suggested-by: default avatarMing Lei <ming.lei@redhat.com>
Signed-off-by: default avatarUday Shankar <ushankar@purestorage.com>
Reviewed-by: default avatarCaleb Sander Mateos <csander@purestorage.com>
Reviewed-by: default avatarMing Lei <ming.lei@redhat.com>
Signed-off-by: default avatarCaleb Sander Mateos <csander@purestorage.com>
Link: https://lore.kernel.org/r/20250430225234.2676781-2-csander@purestorage.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 9712c57e
Loading
Loading
Loading
Loading
+43 −47
Original line number Diff line number Diff line
@@ -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 @@ static int ublk_fetch(struct io_uring_cmd *cmd, struct ublk_queue *ubq,
	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))