From 3446583f81fc3b98dddaac15b37d9c4ff2b569af Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sun, 13 Jul 2025 22:34:03 +0800 Subject: [PATCH] ublk: add helper ublk_check_fetch_buf() Add a helper ublk_check_fetch_buf() to validate UBLK_IO_FETCH_REQ's addr. This doesn't require access to the ublk_io, so it can be done before taking the ublk_device mutex. This way also fixes one missing return value of -EINVAL in case of early failure from ublk_fetch(). Fixes: b69b8edfb27d ("ublk: properly serialize all FETCH_REQs") Reviewed-by: Caleb Sander Mateos Signed-off-by: Ming Lei Link: https://lore.kernel.org/r/20250713143415.2857561-9-ming.lei@redhat.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index c69d4fafc6ccb..1b22fd5f5610d 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -2165,6 +2165,22 @@ static int ublk_unregister_io_buf(struct io_uring_cmd *cmd, return io_buffer_unregister_bvec(cmd, index, issue_flags); } +static int ublk_check_fetch_buf(const struct ublk_queue *ubq, __u64 buf_addr) +{ + if (ublk_need_map_io(ubq)) { + /* + * FETCH_RQ has to provide IO buffer if NEED GET + * DATA is not enabled + */ + if (!buf_addr && !ublk_need_get_data(ubq)) + return -EINVAL; + } else if (buf_addr) { + /* User copy requires addr to be unset */ + return -EINVAL; + } + return 0; +} + static int ublk_fetch(struct io_uring_cmd *cmd, struct ublk_queue *ubq, struct ublk_io *io, __u64 buf_addr) { @@ -2191,19 +2207,6 @@ static int ublk_fetch(struct io_uring_cmd *cmd, struct ublk_queue *ubq, WARN_ON_ONCE(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV); - if (ublk_need_map_io(ubq)) { - /* - * FETCH_RQ has to provide IO buffer if NEED GET - * DATA is not enabled - */ - if (!buf_addr && !ublk_need_get_data(ubq)) - goto out; - } else if (buf_addr) { - /* User copy requires addr to be unset */ - ret = -EINVAL; - goto out; - } - ublk_fill_io_cmd(io, cmd); ret = ublk_config_io_buf(ubq, io, cmd, buf_addr, NULL); if (ret) @@ -2316,6 +2319,9 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd, io = &ubq->ios[tag]; /* UBLK_IO_FETCH_REQ can be handled on any task, which sets io->task */ if (unlikely(_IOC_NR(cmd_op) == UBLK_IO_FETCH_REQ)) { + ret = ublk_check_fetch_buf(ubq, ub_cmd->addr); + if (ret) + goto out; ret = ublk_fetch(cmd, ubq, io, ub_cmd->addr); if (ret) goto out; -- 2.47.2