Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ublk: move ublk_mark_io_ready() out of __ublk_fetch()

ublk_batch_prep_io() calls __ublk_fetch() while holding io->lock
spinlock. When the last IO makes the device ready, ublk_mark_io_ready()
tries to acquire ub->cancel_mutex which can sleep, causing a
sleeping-while-atomic bug.

Fix by moving ublk_mark_io_ready() out of __ublk_fetch() and into the
callers (ublk_fetch and ublk_batch_prep_io) after the spinlock is
released.

Reported-by: Jens Axboe <axboe@kernel.dk>
Fixes: b256795b3606 ("ublk: handle UBLK_U_IO_PREP_IO_CMDS")
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Ming Lei and committed by
Jens Axboe
dbc635c4 e8cd481c

+5 -1
+5 -1
drivers/block/ublk_drv.c
··· 3064 3064 WRITE_ONCE(io->task, NULL); 3065 3065 else 3066 3066 WRITE_ONCE(io->task, get_task_struct(current)); 3067 - ublk_mark_io_ready(ub, q_id); 3068 3067 3069 3068 return 0; 3070 3069 } ··· 3082 3083 ret = __ublk_fetch(cmd, ub, io, q_id); 3083 3084 if (!ret) 3084 3085 ret = ublk_config_io_buf(ub, io, cmd, buf_addr, NULL); 3086 + if (!ret) 3087 + ublk_mark_io_ready(ub, q_id); 3085 3088 mutex_unlock(&ub->mutex); 3086 3089 return ret; 3087 3090 } ··· 3484 3483 if (!ret) 3485 3484 io->buf = buf; 3486 3485 ublk_io_unlock(io); 3486 + 3487 + if (!ret) 3488 + ublk_mark_io_ready(data->ub, ubq->q_id); 3487 3489 3488 3490 return ret; 3489 3491 }