ublk_drv: support UBLK_F_USER_RECOVERY_REISSUE
authorZiyangZhang <ZiyangZhang@linux.alibaba.com>
Fri, 23 Sep 2022 15:39:17 +0000 (23:39 +0800)
committerJens Axboe <axboe@kernel.dk>
Sat, 24 Sep 2022 01:09:56 +0000 (19:09 -0600)
UBLK_F_USER_RECOVERY_REISSUE implies that:
With a dying ubq_daemon, ublk_drv let monitor_work requeues rq issued to
userspace(ublksrv) before the ubq_daemon is dying.

UBLK_F_USER_RECOVERY_REISSUE is designed for backends which:
(1) tolerate double-write since ublk_drv may issue the same rq
    twice.
(2) does not let frontend users get I/O error, such as read-only FS
    and VM backend.

Signed-off-by: ZiyangZhang <ZiyangZhang@linux.alibaba.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20220923153919.44078-6-ZiyangZhang@linux.alibaba.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/ublk_drv.c
include/uapi/linux/ublk_cmd.h

index 3cdcc9b..76ee41e 100644 (file)
@@ -50,7 +50,8 @@
 #define UBLK_F_ALL (UBLK_F_SUPPORT_ZERO_COPY \
                | UBLK_F_URING_CMD_COMP_IN_TASK \
                | UBLK_F_NEED_GET_DATA \
-               | UBLK_F_USER_RECOVERY)
+               | UBLK_F_USER_RECOVERY \
+               | UBLK_F_USER_RECOVERY_REISSUE)
 
 /* All UBLK_PARAM_TYPE_* should be included here */
 #define UBLK_PARAM_TYPE_ALL (UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DISCARD)
@@ -325,6 +326,15 @@ static inline int ublk_queue_cmd_buf_size(struct ublk_device *ub, int q_id)
                        PAGE_SIZE);
 }
 
+static inline bool ublk_queue_can_use_recovery_reissue(
+               struct ublk_queue *ubq)
+{
+       if ((ubq->flags & UBLK_F_USER_RECOVERY) &&
+                       (ubq->flags & UBLK_F_USER_RECOVERY_REISSUE))
+               return true;
+       return false;
+}
+
 static inline bool ublk_queue_can_use_recovery(
                struct ublk_queue *ubq)
 {
@@ -629,13 +639,17 @@ static void ublk_complete_rq(struct request *req)
  * Also aborting may not be started yet, keep in mind that one failed
  * request may be issued by block layer again.
  */
-static void __ublk_fail_req(struct ublk_io *io, struct request *req)
+static void __ublk_fail_req(struct ublk_queue *ubq, struct ublk_io *io,
+               struct request *req)
 {
        WARN_ON_ONCE(io->flags & UBLK_IO_FLAG_ACTIVE);
 
        if (!(io->flags & UBLK_IO_FLAG_ABORTED)) {
                io->flags |= UBLK_IO_FLAG_ABORTED;
-               blk_mq_end_request(req, BLK_STS_IOERR);
+               if (ublk_queue_can_use_recovery_reissue(ubq))
+                       blk_mq_requeue_request(req, false);
+               else
+                       blk_mq_end_request(req, BLK_STS_IOERR);
        }
 }
 
@@ -962,7 +976,7 @@ static void ublk_abort_queue(struct ublk_device *ub, struct ublk_queue *ubq)
                         */
                        rq = blk_mq_tag_to_rq(ub->tag_set.tags[ubq->q_id], i);
                        if (rq)
-                               __ublk_fail_req(io, rq);
+                               __ublk_fail_req(ubq, io, rq);
                }
        }
        ublk_put_device(ub);
index 340ff14..3323706 100644 (file)
@@ -76,6 +76,8 @@
 
 #define UBLK_F_USER_RECOVERY   (1UL << 3)
 
+#define UBLK_F_USER_RECOVERY_REISSUE   (1UL << 4)
+
 /* device state */
 #define UBLK_S_DEV_DEAD        0
 #define UBLK_S_DEV_LIVE        1