diff options
author | Christoph Hellwig <hch@lst.de> | 2015-08-27 15:17:00 +0300 |
---|---|---|
committer | James Bottomley <JBottomley@Odin.com> | 2015-08-28 23:14:57 +0300 |
commit | e959ed9a44c5239863ca6db42cb37130bee3c7a3 (patch) | |
tree | 248382f514a1eb44b910886488ae94e056890957 /drivers/scsi/scsi_dh.c | |
parent | ee14c674e8fc57251223054fb52dc0ecfe711028 (diff) | |
download | linux-e959ed9a44c5239863ca6db42cb37130bee3c7a3.tar.xz |
scsi_dh: add a common helper to get a scsi_device from a request_queue
And cleanup the various messy opencoded versions of this. Note that this
moves the sdev_state checks outside the queue_lock coverage, but as
we don't hold the lock over the activation they are only advisory anyway.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <JBottomley@Odin.com>
Diffstat (limited to 'drivers/scsi/scsi_dh.c')
-rw-r--r-- | drivers/scsi/scsi_dh.c | 99 |
1 files changed, 46 insertions, 53 deletions
diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c index 33c1148ff3b5..2e1db5738ae1 100644 --- a/drivers/scsi/scsi_dh.c +++ b/drivers/scsi/scsi_dh.c @@ -283,6 +283,20 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) } EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); +static struct scsi_device *get_sdev_from_queue(struct request_queue *q) +{ + struct scsi_device *sdev; + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + sdev = q->queuedata; + if (!sdev || !get_device(&sdev->sdev_gendev)) + sdev = NULL; + spin_unlock_irqrestore(q->queue_lock, flags); + + return sdev; +} + /* * scsi_dh_activate - activate the path associated with the scsi_device * corresponding to the given request queue. @@ -298,41 +312,37 @@ EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); */ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) { - int err = 0; - unsigned long flags; struct scsi_device *sdev; - struct device *dev = NULL; + int err = SCSI_DH_NOSYS; - spin_lock_irqsave(q->queue_lock, flags); - sdev = q->queuedata; + sdev = get_sdev_from_queue(q); if (!sdev) { - spin_unlock_irqrestore(q->queue_lock, flags); - err = SCSI_DH_NOSYS; if (fn) fn(data, err); return err; } - dev = get_device(&sdev->sdev_gendev); - if (!sdev->handler || !dev || - sdev->sdev_state == SDEV_CANCEL || + if (!sdev->handler) + goto out_fn; + if (sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL) - err = SCSI_DH_NOSYS; - if (sdev->sdev_state == SDEV_OFFLINE) - err = SCSI_DH_DEV_OFFLINED; - spin_unlock_irqrestore(q->queue_lock, flags); + goto out_fn; - if (err) { - if (fn) - fn(data, err); - goto out; - } + err = SCSI_DH_DEV_OFFLINED; + if (sdev->sdev_state == SDEV_OFFLINE) + goto out_fn; if (sdev->handler->activate) err = sdev->handler->activate(sdev, fn, data); -out: - put_device(dev); + +out_put_device: + put_device(&sdev->sdev_gendev); return err; + +out_fn: + if (fn) + fn(data, err); + goto out_put_device; } EXPORT_SYMBOL_GPL(scsi_dh_activate); @@ -348,21 +358,15 @@ EXPORT_SYMBOL_GPL(scsi_dh_activate); */ int scsi_dh_set_params(struct request_queue *q, const char *params) { - int err = -SCSI_DH_NOSYS; - unsigned long flags; struct scsi_device *sdev; + int err = -SCSI_DH_NOSYS; - spin_lock_irqsave(q->queue_lock, flags); - sdev = q->queuedata; - if (sdev->handler && - sdev->handler->set_params && - get_device(&sdev->sdev_gendev)) - err = 0; - spin_unlock_irqrestore(q->queue_lock, flags); - - if (err) + sdev = get_sdev_from_queue(q); + if (!sdev) return err; - err = sdev->handler->set_params(sdev, params); + + if (sdev->handler && sdev->handler->set_params) + err = sdev->handler->set_params(sdev, params); put_device(&sdev->sdev_gendev); return err; } @@ -376,23 +380,19 @@ EXPORT_SYMBOL_GPL(scsi_dh_set_params); */ int scsi_dh_attach(struct request_queue *q, const char *name) { - unsigned long flags; struct scsi_device *sdev; struct scsi_device_handler *scsi_dh; int err = 0; - scsi_dh = scsi_dh_lookup(name); - if (!scsi_dh) - return -EINVAL; - - spin_lock_irqsave(q->queue_lock, flags); - sdev = q->queuedata; - if (!sdev || !get_device(&sdev->sdev_gendev)) - err = -ENODEV; - spin_unlock_irqrestore(q->queue_lock, flags); + sdev = get_sdev_from_queue(q); + if (!sdev) + return -ENODEV; - if (err) - return err; + scsi_dh = scsi_dh_lookup(name); + if (!scsi_dh) { + err = -EINVAL; + goto out_put_device; + } if (sdev->handler) { if (sdev->handler != scsi_dh) @@ -419,22 +419,15 @@ EXPORT_SYMBOL_GPL(scsi_dh_attach); */ const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp) { - unsigned long flags; struct scsi_device *sdev; const char *handler_name = NULL; - spin_lock_irqsave(q->queue_lock, flags); - sdev = q->queuedata; - if (!sdev || !get_device(&sdev->sdev_gendev)) - sdev = NULL; - spin_unlock_irqrestore(q->queue_lock, flags); - + sdev = get_sdev_from_queue(q); if (!sdev) return NULL; if (sdev->handler) handler_name = kstrdup(sdev->handler->name, gfp); - put_device(&sdev->sdev_gendev); return handler_name; } |