ublk: refactor auto buffer register in ublk_dispatch_req()

Refactor auto buffer register code and prepare for supporting batch IO
feature, and the main motivation is to put 'ublk_io' operation code
together, so that per-io lock can be applied for the code block.

The key changes are:
- Rename ublk_auto_buf_reg() as ublk_do_auto_buf_reg()
- Introduce an enum `auto_buf_reg_res` to represent the result of
  the buffer registration attempt (FAIL, FALLBACK, OK).
- Split the existing `ublk_do_auto_buf_reg` function into two:
  - `__ublk_do_auto_buf_reg`: Performs the actual buffer registration
    and returns the `auto_buf_reg_res` status.
  - `ublk_do_auto_buf_reg`: A wrapper that calls the internal function
    and handles the I/O preparation based on the result.
- Introduce `ublk_prep_auto_buf_reg_io` to encapsulate the logic for
  preparing the I/O for completion after buffer registration.
- Pass the `tag` directly to `ublk_auto_buf_reg_fallback` to avoid
  recalculating it.

This refactoring makes the control flow clearer and isolates the different
stages of the auto buffer registration process.

Reviewed-by: Caleb Sander Mateos <csander@purestorage.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Ming Lei 2025-11-21 09:58:26 +08:00 committed by Jens Axboe
parent 8d61ece156
commit 0a9beafa7c
1 changed files with 43 additions and 21 deletions

View File

@ -1168,15 +1168,35 @@ static inline void __ublk_abort_rq(struct ublk_queue *ubq,
} }
static void static void
ublk_auto_buf_reg_fallback(const struct ublk_queue *ubq, struct ublk_io *io) ublk_auto_buf_reg_fallback(const struct ublk_queue *ubq, unsigned tag)
{ {
unsigned tag = io - ubq->ios;
struct ublksrv_io_desc *iod = ublk_get_iod(ubq, tag); struct ublksrv_io_desc *iod = ublk_get_iod(ubq, tag);
iod->op_flags |= UBLK_IO_F_NEED_REG_BUF; iod->op_flags |= UBLK_IO_F_NEED_REG_BUF;
} }
static bool ublk_auto_buf_reg(const struct ublk_queue *ubq, struct request *req, enum auto_buf_reg_res {
AUTO_BUF_REG_FAIL,
AUTO_BUF_REG_FALLBACK,
AUTO_BUF_REG_OK,
};
static void ublk_prep_auto_buf_reg_io(const struct ublk_queue *ubq,
struct request *req, struct ublk_io *io,
struct io_uring_cmd *cmd,
enum auto_buf_reg_res res)
{
if (res == AUTO_BUF_REG_OK) {
io->task_registered_buffers = 1;
io->buf_ctx_handle = io_uring_cmd_ctx_handle(cmd);
io->flags |= UBLK_IO_FLAG_AUTO_BUF_REG;
}
ublk_init_req_ref(ubq, io);
__ublk_prep_compl_io_cmd(io, req);
}
static enum auto_buf_reg_res
__ublk_do_auto_buf_reg(const struct ublk_queue *ubq, struct request *req,
struct ublk_io *io, struct io_uring_cmd *cmd, struct ublk_io *io, struct io_uring_cmd *cmd,
unsigned int issue_flags) unsigned int issue_flags)
{ {
@ -1186,29 +1206,27 @@ static bool ublk_auto_buf_reg(const struct ublk_queue *ubq, struct request *req,
io->buf.auto_reg.index, issue_flags); io->buf.auto_reg.index, issue_flags);
if (ret) { if (ret) {
if (io->buf.auto_reg.flags & UBLK_AUTO_BUF_REG_FALLBACK) { if (io->buf.auto_reg.flags & UBLK_AUTO_BUF_REG_FALLBACK) {
ublk_auto_buf_reg_fallback(ubq, io); ublk_auto_buf_reg_fallback(ubq, req->tag);
return true; return AUTO_BUF_REG_FALLBACK;
} }
blk_mq_end_request(req, BLK_STS_IOERR); blk_mq_end_request(req, BLK_STS_IOERR);
return false; return AUTO_BUF_REG_FAIL;
} }
io->task_registered_buffers = 1; return AUTO_BUF_REG_OK;
io->buf_ctx_handle = io_uring_cmd_ctx_handle(cmd);
io->flags |= UBLK_IO_FLAG_AUTO_BUF_REG;
return true;
} }
static bool ublk_prep_auto_buf_reg(struct ublk_queue *ubq, static void ublk_do_auto_buf_reg(const struct ublk_queue *ubq, struct request *req,
struct request *req, struct ublk_io *io, struct ublk_io *io, struct io_uring_cmd *cmd,
struct io_uring_cmd *cmd,
unsigned int issue_flags) unsigned int issue_flags)
{ {
ublk_init_req_ref(ubq, io); enum auto_buf_reg_res res = __ublk_do_auto_buf_reg(ubq, req, io, cmd,
if (ublk_support_auto_buf_reg(ubq) && ublk_rq_has_data(req)) issue_flags);
return ublk_auto_buf_reg(ubq, req, io, cmd, issue_flags);
return true; if (res != AUTO_BUF_REG_FAIL) {
ublk_prep_auto_buf_reg_io(ubq, req, io, cmd, res);
io_uring_cmd_done(cmd, UBLK_IO_RES_OK, issue_flags);
}
} }
static bool ublk_start_io(const struct ublk_queue *ubq, struct request *req, static bool ublk_start_io(const struct ublk_queue *ubq, struct request *req,
@ -1281,8 +1299,12 @@ static void ublk_dispatch_req(struct ublk_queue *ubq,
if (!ublk_start_io(ubq, req, io)) if (!ublk_start_io(ubq, req, io))
return; return;
if (ublk_prep_auto_buf_reg(ubq, req, io, io->cmd, issue_flags)) if (ublk_support_auto_buf_reg(ubq) && ublk_rq_has_data(req)) {
ublk_do_auto_buf_reg(ubq, req, io, io->cmd, issue_flags);
} else {
ublk_init_req_ref(ubq, io);
ublk_complete_io_cmd(io, req, UBLK_IO_RES_OK, issue_flags); ublk_complete_io_cmd(io, req, UBLK_IO_RES_OK, issue_flags);
}
} }
static void ublk_cmd_tw_cb(struct io_uring_cmd *cmd, static void ublk_cmd_tw_cb(struct io_uring_cmd *cmd,