forked from Minki/linux
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: 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>
This commit is contained in:
parent
bbae8d1f52
commit
a0d41dc113
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user