Except for scsi_internal_device_unblock() all SCSI device state changes happen via scsi_device_set_state(). Modify scsi_internal_device_unblock() such that it uses scsi_device_set_state() to change the device state. This requires modifying scsi_device_set_state() such that it allows the transition from SDEV_CREATED_BLOCK to the SDEV_OFFLINE and SDEV_TRANSPORT_OFFLINE states. Note: since the SDEV_CREATED_BLOCK to SDEV_{TRANSPORT_,}OFFLINE transition is now allowed, direct scsi_device_set_state() calls that change the device state from SDEV_CREATED_BLOCK into SDEV_*OFFLINE will now proceed instead of being rejected. As far as I have been able to verify this behavior change is fine for all upstream SCSI transport drivers and SCSI LLDs. Signed-off-by: Bart Van Assche <bvanassche@xxxxxxx> Cc: Mike Christie <michaelc@xxxxxxxxxxx> Cc: Hannes Reinecke <hare@xxxxxxx> Cc: Roland Dreier <roland@xxxxxxxxxx> --- drivers/scsi/scsi_lib.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 124392f..9eb05a7 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2147,6 +2147,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) case SDEV_RUNNING: case SDEV_QUIESCE: case SDEV_BLOCK: + case SDEV_CREATED_BLOCK: break; default: goto illegal; @@ -2501,29 +2502,21 @@ scsi_internal_device_unblock(struct scsi_device *sdev, { struct request_queue *q = sdev->request_queue; unsigned long flags; + int res; /* * Try to transition the scsi device to SDEV_RUNNING or one of the * offlined states and goose the device queue if successful. */ - if ((sdev->sdev_state == SDEV_BLOCK) || - (sdev->sdev_state == SDEV_TRANSPORT_OFFLINE)) - sdev->sdev_state = new_state; - else if (sdev->sdev_state == SDEV_CREATED_BLOCK) { - if (new_state == SDEV_TRANSPORT_OFFLINE || - new_state == SDEV_OFFLINE) - sdev->sdev_state = new_state; - else - sdev->sdev_state = SDEV_CREATED; - } else if (sdev->sdev_state != SDEV_CANCEL && - sdev->sdev_state != SDEV_OFFLINE) - return -EINVAL; - - spin_lock_irqsave(q->queue_lock, flags); - blk_start_queue(q); - spin_unlock_irqrestore(q->queue_lock, flags); - - return 0; + if (sdev->sdev_state == SDEV_CREATED_BLOCK && new_state == SDEV_RUNNING) + new_state = SDEV_CREATED; + res = scsi_device_set_state(sdev, new_state); + if (!scsi_device_blocked(sdev)) { + spin_lock_irqsave(q->queue_lock, flags); + blk_start_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + } + return res; } EXPORT_SYMBOL_GPL(scsi_internal_device_unblock); -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html