Skip to content

Commit d2b9f12

Browse files
Ming Leiaxboe
authored andcommitted
scsi: avoid to quiesce sdev->request_queue two times
For fixing queue quiesce race between driver and block layer(elevator switch, update nr_requests, ...), we need to support concurrent quiesce and unquiesce, which requires the two to be balanced. blk_mq_quiesce_queue() calls blk_mq_quiesce_queue_nowait() for updating quiesce depth and marking the flag, then scsi_internal_device_block() calls blk_mq_quiesce_queue_nowait() two times actually. Fix the double quiesce and keep quiesce and unquiesce balanced. Reported-by: Yi Zhang <[email protected]> Fixes: e70feb8 ("blk-mq: support concurrent queue quiesce/unquiesce") Signed-off-by: Ming Lei <[email protected]> Reviewed-by: Martin K. Petersen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 9ef4d02 commit d2b9f12

File tree

1 file changed

+14
-15
lines changed

1 file changed

+14
-15
lines changed

drivers/scsi/scsi_lib.c

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2630,6 +2630,14 @@ scsi_target_resume(struct scsi_target *starget)
26302630
}
26312631
EXPORT_SYMBOL(scsi_target_resume);
26322632

2633+
static int __scsi_internal_device_block_nowait(struct scsi_device *sdev)
2634+
{
2635+
if (scsi_device_set_state(sdev, SDEV_BLOCK))
2636+
return scsi_device_set_state(sdev, SDEV_CREATED_BLOCK);
2637+
2638+
return 0;
2639+
}
2640+
26332641
/**
26342642
* scsi_internal_device_block_nowait - try to transition to the SDEV_BLOCK state
26352643
* @sdev: device to block
@@ -2646,24 +2654,16 @@ EXPORT_SYMBOL(scsi_target_resume);
26462654
*/
26472655
int scsi_internal_device_block_nowait(struct scsi_device *sdev)
26482656
{
2649-
struct request_queue *q = sdev->request_queue;
2650-
int err = 0;
2651-
2652-
err = scsi_device_set_state(sdev, SDEV_BLOCK);
2653-
if (err) {
2654-
err = scsi_device_set_state(sdev, SDEV_CREATED_BLOCK);
2655-
2656-
if (err)
2657-
return err;
2658-
}
2657+
int ret = __scsi_internal_device_block_nowait(sdev);
26592658

26602659
/*
26612660
* The device has transitioned to SDEV_BLOCK. Stop the
26622661
* block layer from calling the midlayer with this device's
26632662
* request queue.
26642663
*/
2665-
blk_mq_quiesce_queue_nowait(q);
2666-
return 0;
2664+
if (!ret)
2665+
blk_mq_quiesce_queue_nowait(sdev->request_queue);
2666+
return ret;
26672667
}
26682668
EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait);
26692669

@@ -2684,13 +2684,12 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait);
26842684
*/
26852685
static int scsi_internal_device_block(struct scsi_device *sdev)
26862686
{
2687-
struct request_queue *q = sdev->request_queue;
26882687
int err;
26892688

26902689
mutex_lock(&sdev->state_mutex);
2691-
err = scsi_internal_device_block_nowait(sdev);
2690+
err = __scsi_internal_device_block_nowait(sdev);
26922691
if (err == 0)
2693-
blk_mq_quiesce_queue(q);
2692+
blk_mq_quiesce_queue(sdev->request_queue);
26942693
mutex_unlock(&sdev->state_mutex);
26952694

26962695
return err;

0 commit comments

Comments
 (0)