ublk: run auto buf unregisgering in same io_ring_ctx with registering
authorMing Lei <ming.lei@redhat.com>
Thu, 22 May 2025 15:20:40 +0000 (23:20 +0800)
committerJens Axboe <axboe@kernel.dk>
Thu, 22 May 2025 16:03:55 +0000 (10:03 -0600)
UBLK_F_AUTO_BUF_REG requires that the buffer registered automatically
is unregistered in same `io_ring_ctx`, so check it explicitly.

Document this requirement for UBLK_F_AUTO_BUF_REG.

Drop WARN_ON_ONCE() which is triggered from userspace code path.

Fixes: 99c1e4eb6a3f ("ublk: register buffer to local io_uring with provided buf index via UBLK_F_AUTO_BUF_REG")
Reported-by: Caleb Sander Mateos <csander@purestorage.com>
Reviewed-by: Caleb Sander Mateos <csander@purestorage.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20250522152043.399824-3-ming.lei@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/ublk_drv.c
include/uapi/linux/ublk_cmd.h

index f818733901dc5d37a85ce18a1db90730936c9b88..33fadca3ee9054456db67dc0788f37d9701417a5 100644 (file)
@@ -84,6 +84,7 @@ struct ublk_rq_data {
 
        /* for auto-unregister buffer in case of UBLK_F_AUTO_BUF_REG */
        u16 buf_index;
+       void *buf_ctx_handle;
 };
 
 struct ublk_uring_cmd_pdu {
@@ -1211,6 +1212,8 @@ static bool ublk_auto_buf_reg(struct request *req, struct ublk_io *io,
        }
        /* one extra reference is dropped by ublk_io_release */
        refcount_set(&data->ref, 2);
+
+       data->buf_ctx_handle = io_uring_cmd_ctx_handle(io->cmd);
        /* store buffer index in request payload */
        data->buf_index = pdu->buf.index;
        io->flags |= UBLK_IO_FLAG_AUTO_BUF_REG;
@@ -2111,12 +2114,22 @@ static int ublk_commit_and_fetch(const struct ublk_queue *ubq,
        if (ublk_support_auto_buf_reg(ubq)) {
                int ret;
 
+               /*
+                * `UBLK_F_AUTO_BUF_REG` only works iff `UBLK_IO_FETCH_REQ`
+                * and `UBLK_IO_COMMIT_AND_FETCH_REQ` are issued from same
+                * `io_ring_ctx`.
+                *
+                * If this uring_cmd's io_ring_ctx isn't same with the
+                * one for registering the buffer, it is ublk server's
+                * responsibility for unregistering the buffer, otherwise
+                * this ublk request gets stuck.
+                */
                if (io->flags & UBLK_IO_FLAG_AUTO_BUF_REG) {
                        struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
 
-                       WARN_ON_ONCE(io_buffer_unregister_bvec(cmd,
-                                               data->buf_index,
-                                               issue_flags));
+                       if (data->buf_ctx_handle == io_uring_cmd_ctx_handle(cmd))
+                               io_buffer_unregister_bvec(cmd, data->buf_index,
+                                               issue_flags);
                        io->flags &= ~UBLK_IO_FLAG_AUTO_BUF_REG;
                }
 
index c4b9942697fcce4e0f7f675f2c69bd714478f99f..1c40632cb164956add53f47b8e72ed22413313ae 100644 (file)
  *
  * For using this feature:
  *
- * - ublk server has to create sparse buffer table
+ * - ublk server has to create sparse buffer table on the same `io_ring_ctx`
+ *   for issuing `UBLK_IO_FETCH_REQ` and `UBLK_IO_COMMIT_AND_FETCH_REQ`.
+ *   If uring_cmd isn't issued on same `io_ring_ctx`, it is ublk server's
+ *   responsibility to unregister the buffer by issuing `IO_UNREGISTER_IO_BUF`
+ *   manually, otherwise this ublk request won't complete.
  *
  * - ublk server passes auto buf register data via uring_cmd's sqe->addr,
  *   `struct ublk_auto_buf_reg` is populated from sqe->addr, please see