From 87213b0d847cd300285b5545598e0548baeb5208 Mon Sep 17 00:00:00 2001 From: Caleb Sander Mateos Date: Mon, 1 Dec 2025 14:41:44 -0700 Subject: ublk: allow non-blocking ctrl cmds in IO_URING_F_NONBLOCK issue Handling most of the ublksrv_ctrl_cmd opcodes require locking a mutex, so ublk_ctrl_uring_cmd() bails out with EAGAIN when called with the IO_URING_F_NONBLOCK issue flag. However, several opcodes can be handled without blocking: - UBLK_CMD_GET_QUEUE_AFFINITY - UBLK_CMD_GET_DEV_INFO - UBLK_CMD_GET_DEV_INFO2 - UBLK_U_CMD_GET_FEATURES Handle these opcodes synchronously instead of returning EAGAIN so io_uring doesn't need to issue the command via the worker thread pool. Signed-off-by: Caleb Sander Mateos Reviewed-by: Ming Lei Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 2c715df63f23..3ecaafacfd20 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -3673,6 +3673,19 @@ exit: return ret; } +static bool ublk_ctrl_uring_cmd_may_sleep(u32 cmd_op) +{ + switch (_IOC_NR(cmd_op)) { + case UBLK_CMD_GET_QUEUE_AFFINITY: + case UBLK_CMD_GET_DEV_INFO: + case UBLK_CMD_GET_DEV_INFO2: + case _IOC_NR(UBLK_U_CMD_GET_FEATURES): + return false; + default: + return true; + } +} + static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags) { @@ -3681,7 +3694,8 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd, u32 cmd_op = cmd->cmd_op; int ret = -EINVAL; - if (issue_flags & IO_URING_F_NONBLOCK) + if (ublk_ctrl_uring_cmd_may_sleep(cmd_op) && + issue_flags & IO_URING_F_NONBLOCK) return -EAGAIN; ublk_ctrl_cmd_dump(cmd); -- cgit v1.2.3 From 53280e398471f0bddbb17b798a63d41264651325 Mon Sep 17 00:00:00 2001 From: Shida Zhang Date: Tue, 9 Dec 2025 17:01:56 +0800 Subject: bcache: fix improper use of bi_end_io Don't call bio->bi_end_io() directly. Use the bio_endio() helper function instead, which handles completion more safely and uniformly. Suggested-by: Christoph Hellwig Reviewed-by: Christoph Hellwig Signed-off-by: Shida Zhang Signed-off-by: Jens Axboe --- drivers/md/bcache/request.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index af345dc6fde1..82fdea7dea7a 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -1104,7 +1104,7 @@ static void detached_dev_end_io(struct bio *bio) } kfree(ddip); - bio->bi_end_io(bio); + bio_endio(bio); } static void detached_dev_do_request(struct bcache_device *d, struct bio *bio, @@ -1121,7 +1121,7 @@ static void detached_dev_do_request(struct bcache_device *d, struct bio *bio, ddip = kzalloc(sizeof(struct detached_dev_io_private), GFP_NOIO); if (!ddip) { bio->bi_status = BLK_STS_RESOURCE; - bio->bi_end_io(bio); + bio_endio(bio); return; } @@ -1136,7 +1136,7 @@ static void detached_dev_do_request(struct bcache_device *d, struct bio *bio, if ((bio_op(bio) == REQ_OP_DISCARD) && !bdev_max_discard_sectors(dc->bdev)) - bio->bi_end_io(bio); + detached_dev_end_io(bio); else submit_bio_noacct(bio); } -- cgit v1.2.3 From db339b4067eccb7fa3d9787d5d3ab5d466fd9efa Mon Sep 17 00:00:00 2001 From: Caleb Sander Mateos Date: Mon, 8 Dec 2025 20:14:23 -0700 Subject: ublk: don't mutate struct bio_vec in iteration __bio_for_each_segment() uses the returned struct bio_vec's bv_len field to advance the struct bvec_iter at the end of each loop iteration. So it's incorrect to modify it during the loop. Don't assign to bv_len (or bv_offset, for that matter) in ublk_copy_user_pages(). Signed-off-by: Caleb Sander Mateos Fixes: e87d66ab27ac ("ublk: use rq_for_each_segment() for user copy") Reviewed-by: Ming Lei Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 3ecaafacfd20..df9831783a13 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -926,6 +926,7 @@ static size_t ublk_copy_user_pages(const struct request *req, size_t done = 0; rq_for_each_segment(bv, req, iter) { + unsigned len; void *bv_buf; size_t copied; @@ -934,18 +935,17 @@ static size_t ublk_copy_user_pages(const struct request *req, continue; } - bv.bv_offset += offset; - bv.bv_len -= offset; - bv_buf = bvec_kmap_local(&bv); + len = bv.bv_len - offset; + bv_buf = kmap_local_page(bv.bv_page) + bv.bv_offset + offset; if (dir == ITER_DEST) - copied = copy_to_iter(bv_buf, bv.bv_len, uiter); + copied = copy_to_iter(bv_buf, len, uiter); else - copied = copy_from_iter(bv_buf, bv.bv_len, uiter); + copied = copy_from_iter(bv_buf, len, uiter); kunmap_local(bv_buf); done += copied; - if (copied < bv.bv_len) + if (copied < len) break; offset = 0; -- cgit v1.2.3