Skip to content

Commit c0b79b0

Browse files
Ming Leiaxboe
authored andcommitted
ublk: add timeout handler
Add timeout handler, so that we can provide forward progress guarantee for unprivileged ublk, which can't be trusted. One thing is that sync() calls sync_bdevs(wait) for all block devices after running sync_bdevs(no_wait), and if one device can't move on, the sync() won't return any more. Add timeout for unprivileged ublk to avoid such affect for other users which call sync() syscall. Meantime clear UBLK_F_USER_RECOVERY_REISSUE for unprivileged ublk since that feature may cause IO hang too. Fixes: 4093cb5 ("ublk_drv: add mechanism for supporting unprivileged ublk device") Signed-off-by: Ming Lei <ming.lei@redhat.com> Link: https://lore.kernel.org/r/20230502024231.888498-1-ming.lei@redhat.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 3899d94 commit c0b79b0

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

drivers/block/ublk_drv.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ struct ublk_queue {
129129
unsigned long io_addr; /* mapped vm address */
130130
unsigned int max_io_sz;
131131
bool force_abort;
132+
bool timeout;
132133
unsigned short nr_io_ready; /* how many ios setup */
133134
struct ublk_device *dev;
134135
struct ublk_io ios[];
@@ -894,6 +895,22 @@ static void ublk_queue_cmd(struct ublk_queue *ubq, struct request *rq)
894895
}
895896
}
896897

898+
static enum blk_eh_timer_return ublk_timeout(struct request *rq)
899+
{
900+
struct ublk_queue *ubq = rq->mq_hctx->driver_data;
901+
902+
if (ubq->flags & UBLK_F_UNPRIVILEGED_DEV) {
903+
if (!ubq->timeout) {
904+
send_sig(SIGKILL, ubq->ubq_daemon, 0);
905+
ubq->timeout = true;
906+
}
907+
908+
return BLK_EH_DONE;
909+
}
910+
911+
return BLK_EH_RESET_TIMER;
912+
}
913+
897914
static blk_status_t ublk_queue_rq(struct blk_mq_hw_ctx *hctx,
898915
const struct blk_mq_queue_data *bd)
899916
{
@@ -953,6 +970,7 @@ static const struct blk_mq_ops ublk_mq_ops = {
953970
.queue_rq = ublk_queue_rq,
954971
.init_hctx = ublk_init_hctx,
955972
.init_request = ublk_init_rq,
973+
.timeout = ublk_timeout,
956974
};
957975

958976
static int ublk_ch_open(struct inode *inode, struct file *filp)
@@ -1713,6 +1731,18 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
17131731
else if (!(info.flags & UBLK_F_UNPRIVILEGED_DEV))
17141732
return -EPERM;
17151733

1734+
/*
1735+
* unprivileged device can't be trusted, but RECOVERY and
1736+
* RECOVERY_REISSUE still may hang error handling, so can't
1737+
* support recovery features for unprivileged ublk now
1738+
*
1739+
* TODO: provide forward progress for RECOVERY handler, so that
1740+
* unprivileged device can benefit from it
1741+
*/
1742+
if (info.flags & UBLK_F_UNPRIVILEGED_DEV)
1743+
info.flags &= ~(UBLK_F_USER_RECOVERY_REISSUE |
1744+
UBLK_F_USER_RECOVERY);
1745+
17161746
/* the created device is always owned by current user */
17171747
ublk_store_owner_uid_gid(&info.owner_uid, &info.owner_gid);
17181748

@@ -1981,6 +2011,7 @@ static void ublk_queue_reinit(struct ublk_device *ub, struct ublk_queue *ubq)
19812011
put_task_struct(ubq->ubq_daemon);
19822012
/* We have to reset it to NULL, otherwise ub won't accept new FETCH_REQ */
19832013
ubq->ubq_daemon = NULL;
2014+
ubq->timeout = false;
19842015

19852016
for (i = 0; i < ubq->q_depth; i++) {
19862017
struct ublk_io *io = &ubq->ios[i];

0 commit comments

Comments
 (0)