Commit 263846eb authored by Ming Lei's avatar Ming Lei Committed by Jens Axboe
Browse files

selftests: ublk: simplify loop io completion



Use the added target io handling helpers for simplifying loop io
completion.

Signed-off-by: default avatarMing Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20250322093218.431419-8-ming.lei@redhat.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 8cb9b971
Loading
Loading
Loading
Loading
+47 −44
Original line number Diff line number Diff line
@@ -13,8 +13,22 @@ static enum io_uring_op ublk_to_uring_op(const struct ublksrv_io_desc *iod, int
	assert(0);
}

static int loop_queue_flush_io(struct ublk_queue *q, const struct ublksrv_io_desc *iod, int tag)
{
	unsigned ublk_op = ublksrv_get_op(iod);
	struct io_uring_sqe *sqe[1];

	ublk_queue_alloc_sqes(q, sqe, 1);
	io_uring_prep_fsync(sqe[0], 1 /*fds[1]*/, IORING_FSYNC_DATASYNC);
	io_uring_sqe_set_flags(sqe[0], IOSQE_FIXED_FILE);
	/* bit63 marks us as tgt io */
	sqe[0]->user_data = build_user_data(tag, ublk_op, 0, 1);
	return 1;
}

static int loop_queue_tgt_rw_io(struct ublk_queue *q, const struct ublksrv_io_desc *iod, int tag)
{
	unsigned ublk_op = ublksrv_get_op(iod);
	int zc = ublk_queue_use_zc(q);
	enum io_uring_op op = ublk_to_uring_op(iod, zc);
	struct io_uring_sqe *sqe[3];
@@ -29,98 +43,87 @@ static int loop_queue_tgt_rw_io(struct ublk_queue *q, const struct ublksrv_io_de
				iod->nr_sectors << 9,
				iod->start_sector << 9);
		io_uring_sqe_set_flags(sqe[0], IOSQE_FIXED_FILE);
		q->io_inflight++;
		/* bit63 marks us as tgt io */
		sqe[0]->user_data = build_user_data(tag, op, UBLK_IO_TGT_NORMAL, 1);
		return 0;
		sqe[0]->user_data = build_user_data(tag, ublk_op, 0, 1);
		return 1;
	}

	ublk_queue_alloc_sqes(q, sqe, 3);

	io_uring_prep_buf_register(sqe[0], 0, tag, q->q_id, tag);
	sqe[0]->user_data = build_user_data(tag, 0xfe, 1, 1);
	sqe[0]->flags |= IOSQE_CQE_SKIP_SUCCESS;
	sqe[0]->flags |= IOSQE_IO_LINK;
	sqe[0]->flags |= IOSQE_CQE_SKIP_SUCCESS | IOSQE_IO_HARDLINK;
	sqe[0]->user_data = build_user_data(tag,
			ublk_cmd_op_nr(sqe[0]->cmd_op), 0, 1);

	io_uring_prep_rw(op, sqe[1], 1 /*fds[1]*/, 0,
		iod->nr_sectors << 9,
		iod->start_sector << 9);
	sqe[1]->buf_index = tag;
	sqe[1]->flags |= IOSQE_FIXED_FILE;
	sqe[1]->flags |= IOSQE_IO_LINK;
	sqe[1]->user_data = build_user_data(tag, op, UBLK_IO_TGT_ZC_OP, 1);
	q->io_inflight++;
	sqe[1]->flags |= IOSQE_FIXED_FILE | IOSQE_IO_HARDLINK;
	sqe[1]->user_data = build_user_data(tag, ublk_op, 0, 1);

	io_uring_prep_buf_unregister(sqe[2], 0, tag, q->q_id, tag);
	sqe[2]->user_data = build_user_data(tag, 0xff, UBLK_IO_TGT_ZC_BUF, 1);
	q->io_inflight++;
	sqe[2]->user_data = build_user_data(tag, ublk_cmd_op_nr(sqe[2]->cmd_op), 0, 1);

	return 0;
	return 2;
}

static int loop_queue_tgt_io(struct ublk_queue *q, int tag)
{
	const struct ublksrv_io_desc *iod = ublk_get_iod(q, tag);
	unsigned ublk_op = ublksrv_get_op(iod);
	struct io_uring_sqe *sqe[1];
	int ret;

	switch (ublk_op) {
	case UBLK_IO_OP_FLUSH:
		ublk_queue_alloc_sqes(q, sqe, 1);
		if (!sqe[0])
			return -ENOMEM;
		io_uring_prep_fsync(sqe[0], 1 /*fds[1]*/, IORING_FSYNC_DATASYNC);
		io_uring_sqe_set_flags(sqe[0], IOSQE_FIXED_FILE);
		q->io_inflight++;
		sqe[0]->user_data = build_user_data(tag, ublk_op, UBLK_IO_TGT_NORMAL, 1);
		ret = loop_queue_flush_io(q, iod, tag);
		break;
	case UBLK_IO_OP_WRITE_ZEROES:
	case UBLK_IO_OP_DISCARD:
		return -ENOTSUP;
		ret = -ENOTSUP;
		break;
	case UBLK_IO_OP_READ:
	case UBLK_IO_OP_WRITE:
		loop_queue_tgt_rw_io(q, iod, tag);
		ret = loop_queue_tgt_rw_io(q, iod, tag);
		break;
	default:
		return -EINVAL;
		ret = -EINVAL;
		break;
	}

	ublk_dbg(UBLK_DBG_IO, "%s: tag %d ublk io %x %llx %u\n", __func__, tag,
			iod->op_flags, iod->start_sector, iod->nr_sectors << 9);
	return 1;
	return ret;
}

static int ublk_loop_queue_io(struct ublk_queue *q, int tag)
{
	int queued = loop_queue_tgt_io(q, tag);

	if (queued < 0)
		ublk_complete_io(q, tag, queued);

	ublk_queued_tgt_io(q, tag, queued);
	return 0;
}

static void ublk_loop_io_done(struct ublk_queue *q, int tag,
		const struct io_uring_cqe *cqe)
{
	int cqe_tag = user_data_to_tag(cqe->user_data);
	unsigned tgt_data = user_data_to_tgt_data(cqe->user_data);
	int res = cqe->res;
	unsigned op = user_data_to_op(cqe->user_data);
	struct ublk_io *io = ublk_get_io(q, tag);

	if (cqe->res < 0 || op != ublk_cmd_op_nr(UBLK_U_IO_UNREGISTER_IO_BUF)) {
		if (!io->result)
			io->result = cqe->res;
		if (cqe->res < 0)
			ublk_err("%s: io failed op %x user_data %lx\n",
					__func__, op, cqe->user_data);
	}

	if (res < 0 || tgt_data == UBLK_IO_TGT_NORMAL)
		goto complete;
	/* buffer register op is IOSQE_CQE_SKIP_SUCCESS */
	if (op == ublk_cmd_op_nr(UBLK_U_IO_REGISTER_IO_BUF))
		io->tgt_ios += 1;

	if (tgt_data == UBLK_IO_TGT_ZC_OP) {
		ublk_set_io_res(q, tag, cqe->res);
		goto exit;
	}
	assert(tgt_data == UBLK_IO_TGT_ZC_BUF);
	res = ublk_get_io_res(q, tag);
complete:
	assert(tag == cqe_tag);
	ublk_complete_io(q, tag, res);
exit:
	q->io_inflight--;
	if (ublk_completed_tgt_io(q, tag))
		ublk_complete_io(q, tag, io->result);
}

static int ublk_loop_tgt_init(const struct dev_ctx *ctx, struct ublk_dev *dev)
+0 −4
Original line number Diff line number Diff line
@@ -44,10 +44,6 @@
#define UBLK_MAX_QUEUES                 4
#define UBLK_QUEUE_DEPTH                128

#define UBLK_IO_TGT_NORMAL 		0
#define UBLK_IO_TGT_ZC_BUF 		1
#define UBLK_IO_TGT_ZC_OP 		2

#define UBLK_DBG_DEV            (1U << 0)
#define UBLK_DBG_QUEUE          (1U << 1)
#define UBLK_DBG_IO_CMD         (1U << 2)