ublk: add UBLK_CMD_DEL_DEV_ASYNC
authorMing Lei <ming.lei@redhat.com>
Fri, 23 Feb 2024 07:55:39 +0000 (15:55 +0800)
committerJens Axboe <axboe@kernel.dk>
Thu, 29 Feb 2024 01:47:08 +0000 (18:47 -0700)
The current command UBLK_CMD_DEL_DEV won't return until the device is
released, this way looks more reliable, but makes userspace more
difficult to implement, especially about orders: unmap command
buffer(which holds one ublkc reference), ublkc close,
io_uring_file_unregister, ublkb close.

Add UBLK_CMD_DEL_DEV_ASYNC so that device deletion won't wait release,
then userspace needn't worry about the above order. Actually both loop
and nbd is deleted in this async way.

Signed-off-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20240223075539.89945-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 06d88d2008ba533750c4aa496e6c9b69b7ff7e29..bea3d5cf8a83487909270d5f2398267250507a31 100644 (file)
@@ -2468,7 +2468,7 @@ static inline bool ublk_idr_freed(int id)
        return ptr == NULL;
 }
 
-static int ublk_ctrl_del_dev(struct ublk_device **p_ub)
+static int ublk_ctrl_del_dev(struct ublk_device **p_ub, bool wait)
 {
        struct ublk_device *ub = *p_ub;
        int idx = ub->ub_number;
@@ -2502,7 +2502,7 @@ static int ublk_ctrl_del_dev(struct ublk_device **p_ub)
         * - the device number is freed already, we will not find this
         *   device via ublk_get_device_from_id()
         */
-       if (wait_event_interruptible(ublk_idr_wq, ublk_idr_freed(idx)))
+       if (wait && wait_event_interruptible(ublk_idr_wq, ublk_idr_freed(idx)))
                return -EINTR;
        return 0;
 }
@@ -2901,7 +2901,10 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
                ret = ublk_ctrl_add_dev(cmd);
                break;
        case UBLK_CMD_DEL_DEV:
-               ret = ublk_ctrl_del_dev(&ub);
+               ret = ublk_ctrl_del_dev(&ub, true);
+               break;
+       case UBLK_U_CMD_DEL_DEV_ASYNC:
+               ret = ublk_ctrl_del_dev(&ub, false);
                break;
        case UBLK_CMD_GET_QUEUE_AFFINITY:
                ret = ublk_ctrl_get_queue_affinity(ub, cmd);
index b9cfc5c962682364e6dda544322ec07aa4a1ff83..c8dc5f8ea699627402dc2069615acd066f103981 100644 (file)
@@ -49,6 +49,8 @@
        _IOR('u', UBLK_CMD_GET_DEV_INFO2, struct ublksrv_ctrl_cmd)
 #define UBLK_U_CMD_GET_FEATURES        \
        _IOR('u', 0x13, struct ublksrv_ctrl_cmd)
+#define UBLK_U_CMD_DEL_DEV_ASYNC       \
+       _IOR('u', 0x14, struct ublksrv_ctrl_cmd)
 
 /*
  * 64bits are enough now, and it should be easy to extend in case of