Commit a0d41dc1 authored by ZiyangZhang's avatar ZiyangZhang Committed by Jens Axboe

ublk_drv: support UBLK_F_USER_RECOVERY_REISSUE

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: default avatarZiyangZhang <ZiyangZhang@linux.alibaba.com>
Reviewed-by: default avatarMing Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20220923153919.44078-6-ZiyangZhang@linux.alibaba.comSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent bbae8d1f
...@@ -50,7 +50,8 @@ ...@@ -50,7 +50,8 @@
#define UBLK_F_ALL (UBLK_F_SUPPORT_ZERO_COPY \ #define UBLK_F_ALL (UBLK_F_SUPPORT_ZERO_COPY \
| UBLK_F_URING_CMD_COMP_IN_TASK \ | UBLK_F_URING_CMD_COMP_IN_TASK \
| UBLK_F_NEED_GET_DATA \ | 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 */ /* All UBLK_PARAM_TYPE_* should be included here */
#define UBLK_PARAM_TYPE_ALL (UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DISCARD) #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) ...@@ -325,6 +326,15 @@ static inline int ublk_queue_cmd_buf_size(struct ublk_device *ub, int q_id)
PAGE_SIZE); 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( static inline bool ublk_queue_can_use_recovery(
struct ublk_queue *ubq) struct ublk_queue *ubq)
{ {
...@@ -629,13 +639,17 @@ static void ublk_complete_rq(struct request *req) ...@@ -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 * Also aborting may not be started yet, keep in mind that one failed
* request may be issued by block layer again. * 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); WARN_ON_ONCE(io->flags & UBLK_IO_FLAG_ACTIVE);
if (!(io->flags & UBLK_IO_FLAG_ABORTED)) { if (!(io->flags & UBLK_IO_FLAG_ABORTED)) {
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) ...@@ -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); rq = blk_mq_tag_to_rq(ub->tag_set.tags[ubq->q_id], i);
if (rq) if (rq)
__ublk_fail_req(io, rq); __ublk_fail_req(ubq, io, rq);
} }
} }
ublk_put_device(ub); ublk_put_device(ub);
......
...@@ -76,6 +76,8 @@ ...@@ -76,6 +76,8 @@
#define UBLK_F_USER_RECOVERY (1UL << 3) #define UBLK_F_USER_RECOVERY (1UL << 3)
#define UBLK_F_USER_RECOVERY_REISSUE (1UL << 4)
/* device state */ /* device state */
#define UBLK_S_DEV_DEAD 0 #define UBLK_S_DEV_DEAD 0
#define UBLK_S_DEV_LIVE 1 #define UBLK_S_DEV_LIVE 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment