Commit 4c8a9517 authored by Ming Lei's avatar Ming Lei Committed by Jens Axboe
Browse files

ublk: setup ublk_io correctly in case of ublk_get_data() failure



If ublk_get_data() fails, -EIOCBQUEUED is returned and the current command
becomes ASYNC. And the only reason is that mapping data can't move on,
because of no enough pages or pending signal, then the current ublk request
has to be requeued.

Once the request need to be requeued, we have to setup `ublk_io` correctly,
including io->cmd and flags, otherwise the request may not be forwarded to
ublk server successfully.

Fixes: 9810362a ("ublk: don't call ublk_dispatch_req() for NEED_GET_DATA")
Reported-by: default avatarChanghui Zhong <czhong@redhat.com>
Closes: https://lore.kernel.org/linux-block/CAGVVp+VN9QcpHUz_0nasFf5q9i1gi8H8j-G-6mkBoqa3TyjRHA@mail.gmail.com/


Signed-off-by: default avatarMing Lei <ming.lei@redhat.com>
Tested-by: default avatarChanghui Zhong <czhong@redhat.com>
Link: https://lore.kernel.org/r/20250624104121.859519-1-ming.lei@redhat.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 81b4d1a1
Loading
Loading
Loading
Loading
+25 −10
Original line number Diff line number Diff line
@@ -1148,8 +1148,8 @@ static inline void __ublk_complete_rq(struct request *req)
	blk_mq_end_request(req, res);
}

static void ublk_complete_io_cmd(struct ublk_io *io, struct request *req,
				 int res, unsigned issue_flags)
static struct io_uring_cmd *__ublk_prep_compl_io_cmd(struct ublk_io *io,
						     struct request *req)
{
	/* read cmd first because req will overwrite it */
	struct io_uring_cmd *cmd = io->cmd;
@@ -1164,6 +1164,13 @@ static void ublk_complete_io_cmd(struct ublk_io *io, struct request *req,
	io->flags &= ~UBLK_IO_FLAG_ACTIVE;

	io->req = req;
	return cmd;
}

static void ublk_complete_io_cmd(struct ublk_io *io, struct request *req,
				 int res, unsigned issue_flags)
{
	struct io_uring_cmd *cmd = __ublk_prep_compl_io_cmd(io, req);

	/* tell ublksrv one io request is coming */
	io_uring_cmd_done(cmd, res, 0, issue_flags);
@@ -2157,10 +2164,9 @@ 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)
static bool ublk_get_data(const struct ublk_queue *ubq, struct ublk_io *io,
			  struct request *req)
{
	struct request *req = io->req;

	/*
	 * We have handled UBLK_IO_NEED_GET_DATA command,
	 * so clear UBLK_IO_FLAG_NEED_GET_DATA now and just
@@ -2187,6 +2193,7 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
	u32 cmd_op = cmd->cmd_op;
	unsigned tag = ub_cmd->tag;
	int ret = -EINVAL;
	struct request *req;

	pr_devel("%s: received: cmd op %d queue %d tag %d result %d\n",
			__func__, cmd->cmd_op, ub_cmd->q_id, tag,
@@ -2245,11 +2252,19 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
			goto out;
		break;
	case UBLK_IO_NEED_GET_DATA:
		io->addr = ub_cmd->addr;
		if (!ublk_get_data(ubq, io))
			return -EIOCBQUEUED;

		/*
		 * ublk_get_data() may fail and fallback to requeue, so keep
		 * uring_cmd active first and prepare for handling new requeued
		 * request
		 */
		req = io->req;
		ublk_fill_io_cmd(io, cmd, ub_cmd->addr);
		io->flags &= ~UBLK_IO_FLAG_OWNED_BY_SRV;
		if (likely(ublk_get_data(ubq, io, req))) {
			__ublk_prep_compl_io_cmd(io, req);
			return UBLK_IO_RES_OK;
		}
		break;
	default:
		goto out;
	}