Modify scsi_internal_device_unblock() such that it uses
scsi_device_set_state() to change the device state. This is only
possible by changing scsi_device_set_state() such that it allows
the transition from SDEV_CREATED_BLOCK to the SDEV_OFFLINE and
SDEV_TRANSPORT_OFFLINE states. Notes:
- All callers of scsi_internal_device_unblock() ignore the return
  value of this function.
- 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.

Signed-off-by: Bart Van Assche <bvanass...@acm.org>
Cc: James Bottomley <jbottom...@parallels.com>
Cc: Mike Christie <micha...@cs.wisc.edu>
Cc: Hannes Reinecke <h...@suse.de>
---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to