From 1d5203284d8acbdfdf9b478d434450b34f338f28 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 14 Sep 2014 11:08:21 -0700 Subject: [PATCH] scsi: handle more device handler setup/teardown in common code Move all code to set up and tear down sdev->scsi_dh_data to common code. Signed-off-by: Christoph Hellwig Reviewed-by: Mike Christie Reviewed-by: Hannes Reinecke --- drivers/scsi/device_handler/scsi_dh.c | 29 ++++-- drivers/scsi/device_handler/scsi_dh_alua.c | 107 ++++++++------------ drivers/scsi/device_handler/scsi_dh_emc.c | 58 ++++------- drivers/scsi/device_handler/scsi_dh_hp_sw.c | 86 ++++++---------- drivers/scsi/device_handler/scsi_dh_rdac.c | 53 +++------- include/scsi/scsi_device.h | 2 +- 6 files changed, 128 insertions(+), 207 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c index d8a8aac2c3db..1dba62c5cf6a 100644 --- a/drivers/scsi/device_handler/scsi_dh.c +++ b/drivers/scsi/device_handler/scsi_dh.c @@ -98,7 +98,7 @@ device_handler_match(struct scsi_device_handler *scsi_dh, static int scsi_dh_handler_attach(struct scsi_device *sdev, struct scsi_device_handler *scsi_dh) { - int err = 0; + struct scsi_dh_data *d; if (sdev->scsi_dh_data) { if (sdev->scsi_dh_data->scsi_dh != scsi_dh) @@ -111,15 +111,22 @@ static int scsi_dh_handler_attach(struct scsi_device *sdev, if (!try_module_get(scsi_dh->module)) return -EINVAL; - err = scsi_dh->attach(sdev); - if (err) { + d = scsi_dh->attach(sdev); + if (IS_ERR(d)) { + sdev_printk(KERN_ERR, sdev, "%s: Attach failed (%ld)\n", + scsi_dh->name, PTR_ERR(d)); module_put(scsi_dh->module); - return err; + return PTR_ERR(d); } - kref_init(&sdev->scsi_dh_data->kref); - sdev->scsi_dh_data->sdev = sdev; - return err; + d->scsi_dh = scsi_dh; + kref_init(&d->kref); + d->sdev = sdev; + + spin_lock_irq(sdev->request_queue->queue_lock); + sdev->scsi_dh_data = d; + spin_unlock_irq(sdev->request_queue->queue_lock); + return 0; } static void __detach_handler (struct kref *kref) @@ -127,8 +134,14 @@ static void __detach_handler (struct kref *kref) struct scsi_dh_data *scsi_dh_data = container_of(kref, struct scsi_dh_data, kref); struct scsi_device_handler *scsi_dh = scsi_dh_data->scsi_dh; + struct scsi_device *sdev = scsi_dh_data->sdev; - scsi_dh->detach(scsi_dh_data->sdev); + spin_lock_irq(sdev->request_queue->queue_lock); + sdev->scsi_dh_data = NULL; + spin_unlock_irq(sdev->request_queue->queue_lock); + + scsi_dh->detach(sdev); + sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", scsi_dh->name); module_put(scsi_dh->module); } diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index d9781045c4ee..854b568b9931 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -824,8 +824,49 @@ static bool alua_match(struct scsi_device *sdev) return (scsi_device_tpgs(sdev) != 0); } -static int alua_bus_attach(struct scsi_device *sdev); -static void alua_bus_detach(struct scsi_device *sdev); +/* + * alua_bus_attach - Attach device handler + * @sdev: device to be attached to + */ +static struct scsi_dh_data *alua_bus_attach(struct scsi_device *sdev) +{ + struct alua_dh_data *h; + int err; + + h = kzalloc(sizeof(*h) , GFP_KERNEL); + if (!h) + return ERR_PTR(-ENOMEM); + h->tpgs = TPGS_MODE_UNINITIALIZED; + h->state = TPGS_STATE_OPTIMIZED; + h->group_id = -1; + h->rel_port = -1; + h->buff = h->inq; + h->bufflen = ALUA_INQUIRY_SIZE; + h->sdev = sdev; + + err = alua_initialize(sdev, h); + if (err != SCSI_DH_OK && err != SCSI_DH_DEV_OFFLINED) + goto failed; + + sdev_printk(KERN_NOTICE, sdev, "%s: Attached\n", ALUA_DH_NAME); + return &h->dh_data; +failed: + kfree(h); + return ERR_PTR(-EINVAL); +} + +/* + * alua_bus_detach - Detach device handler + * @sdev: device to be detached from + */ +static void alua_bus_detach(struct scsi_device *sdev) +{ + struct alua_dh_data *h = get_alua_data(sdev); + + if (h->buff && h->inq != h->buff) + kfree(h->buff); + kfree(h); +} static struct scsi_device_handler alua_dh = { .name = ALUA_DH_NAME, @@ -839,68 +880,6 @@ static struct scsi_device_handler alua_dh = { .match = alua_match, }; -/* - * alua_bus_attach - Attach device handler - * @sdev: device to be attached to - */ -static int alua_bus_attach(struct scsi_device *sdev) -{ - struct alua_dh_data *h; - unsigned long flags; - int err = SCSI_DH_OK; - - h = kzalloc(sizeof(*h) , GFP_KERNEL); - if (!h) { - sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n", - ALUA_DH_NAME); - return -ENOMEM; - } - - h->dh_data.scsi_dh = &alua_dh; - h->tpgs = TPGS_MODE_UNINITIALIZED; - h->state = TPGS_STATE_OPTIMIZED; - h->group_id = -1; - h->rel_port = -1; - h->buff = h->inq; - h->bufflen = ALUA_INQUIRY_SIZE; - h->sdev = sdev; - - err = alua_initialize(sdev, h); - if ((err != SCSI_DH_OK) && (err != SCSI_DH_DEV_OFFLINED)) - goto failed; - - spin_lock_irqsave(sdev->request_queue->queue_lock, flags); - sdev->scsi_dh_data = &h->dh_data; - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); - sdev_printk(KERN_NOTICE, sdev, "%s: Attached\n", ALUA_DH_NAME); - - return 0; - -failed: - kfree(h); - sdev_printk(KERN_ERR, sdev, "%s: not attached\n", ALUA_DH_NAME); - return -EINVAL; -} - -/* - * alua_bus_detach - Detach device handler - * @sdev: device to be detached from - */ -static void alua_bus_detach(struct scsi_device *sdev) -{ - struct alua_dh_data *h = get_alua_data(sdev); - unsigned long flags; - - spin_lock_irqsave(sdev->request_queue->queue_lock, flags); - sdev->scsi_dh_data = NULL; - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); - - if (h->buff && h->inq != h->buff) - kfree(h->buff); - kfree(h); - sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", ALUA_DH_NAME); -} - static int __init alua_init(void) { int r; diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index 800deb75a111..6ed1caadbc6a 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c @@ -650,35 +650,14 @@ static bool clariion_match(struct scsi_device *sdev) return false; } -static int clariion_bus_attach(struct scsi_device *sdev); -static void clariion_bus_detach(struct scsi_device *sdev); - -static struct scsi_device_handler clariion_dh = { - .name = CLARIION_NAME, - .module = THIS_MODULE, - .attach = clariion_bus_attach, - .detach = clariion_bus_detach, - .check_sense = clariion_check_sense, - .activate = clariion_activate, - .prep_fn = clariion_prep_fn, - .set_params = clariion_set_params, - .match = clariion_match, -}; - -static int clariion_bus_attach(struct scsi_device *sdev) +static struct scsi_dh_data *clariion_bus_attach(struct scsi_device *sdev) { struct clariion_dh_data *h; - unsigned long flags; int err; h = kzalloc(sizeof(*h) , GFP_KERNEL); - if (!h) { - sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n", - CLARIION_NAME); - return -ENOMEM; - } - - h->dh_data.scsi_dh = &clariion_dh; + if (!h) + return ERR_PTR(-ENOMEM); h->lun_state = CLARIION_LUN_UNINITIALIZED; h->default_sp = CLARIION_UNBOUND_LU; h->current_sp = CLARIION_UNBOUND_LU; @@ -691,40 +670,37 @@ static int clariion_bus_attach(struct scsi_device *sdev) if (err != SCSI_DH_OK) goto failed; - spin_lock_irqsave(sdev->request_queue->queue_lock, flags); - sdev->scsi_dh_data = &h->dh_data; - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); - sdev_printk(KERN_INFO, sdev, "%s: connected to SP %c Port %d (%s, default SP %c)\n", CLARIION_NAME, h->current_sp + 'A', h->port, lun_state[h->lun_state], h->default_sp + 'A'); - - return 0; + return &h->dh_data; failed: kfree(h); - sdev_printk(KERN_ERR, sdev, "%s: not attached\n", - CLARIION_NAME); - return -EINVAL; + return ERR_PTR(-EINVAL); } static void clariion_bus_detach(struct scsi_device *sdev) { struct clariion_dh_data *h = get_clariion_data(sdev); - unsigned long flags; - - spin_lock_irqsave(sdev->request_queue->queue_lock, flags); - sdev->scsi_dh_data = NULL; - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); - - sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", - CLARIION_NAME); kfree(h); } +static struct scsi_device_handler clariion_dh = { + .name = CLARIION_NAME, + .module = THIS_MODULE, + .attach = clariion_bus_attach, + .detach = clariion_bus_detach, + .check_sense = clariion_check_sense, + .activate = clariion_activate, + .prep_fn = clariion_prep_fn, + .set_params = clariion_set_params, + .match = clariion_match, +}; + static int __init clariion_init(void) { int r; diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index 471ffd19f2c5..485d99544a15 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c @@ -340,8 +340,37 @@ static bool hp_sw_match(struct scsi_device *sdev) return false; } -static int hp_sw_bus_attach(struct scsi_device *sdev); -static void hp_sw_bus_detach(struct scsi_device *sdev); +static struct scsi_dh_data *hp_sw_bus_attach(struct scsi_device *sdev) +{ + struct hp_sw_dh_data *h; + int ret; + + h = kzalloc(sizeof(*h), GFP_KERNEL); + if (!h) + return ERR_PTR(-ENOMEM); + h->path_state = HP_SW_PATH_UNINITIALIZED; + h->retries = HP_SW_RETRIES; + h->sdev = sdev; + + ret = hp_sw_tur(sdev, h); + if (ret != SCSI_DH_OK || h->path_state == HP_SW_PATH_UNINITIALIZED) + goto failed; + + sdev_printk(KERN_INFO, sdev, "%s: attached to %s path\n", + HP_SW_NAME, h->path_state == HP_SW_PATH_ACTIVE? + "active":"passive"); + return &h->dh_data; +failed: + kfree(h); + return ERR_PTR(-EINVAL); +} + +static void hp_sw_bus_detach( struct scsi_device *sdev ) +{ + struct hp_sw_dh_data *h = get_hp_sw_data(sdev); + + kfree(h); +} static struct scsi_device_handler hp_sw_dh = { .name = HP_SW_NAME, @@ -353,59 +382,6 @@ static struct scsi_device_handler hp_sw_dh = { .match = hp_sw_match, }; -static int hp_sw_bus_attach(struct scsi_device *sdev) -{ - struct hp_sw_dh_data *h; - unsigned long flags; - int ret; - - h = kzalloc(sizeof(*h), GFP_KERNEL); - if (!h) { - sdev_printk(KERN_ERR, sdev, "%s: Attach Failed\n", - HP_SW_NAME); - return -ENOMEM; - } - - h->dh_data.scsi_dh = &hp_sw_dh; - h->path_state = HP_SW_PATH_UNINITIALIZED; - h->retries = HP_SW_RETRIES; - h->sdev = sdev; - - ret = hp_sw_tur(sdev, h); - if (ret != SCSI_DH_OK || h->path_state == HP_SW_PATH_UNINITIALIZED) - goto failed; - - spin_lock_irqsave(sdev->request_queue->queue_lock, flags); - sdev->scsi_dh_data = &h->dh_data; - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); - - sdev_printk(KERN_INFO, sdev, "%s: attached to %s path\n", - HP_SW_NAME, h->path_state == HP_SW_PATH_ACTIVE? - "active":"passive"); - - return 0; - -failed: - kfree(h); - sdev_printk(KERN_ERR, sdev, "%s: not attached\n", - HP_SW_NAME); - return -EINVAL; -} - -static void hp_sw_bus_detach( struct scsi_device *sdev ) -{ - struct hp_sw_dh_data *h = get_hp_sw_data(sdev); - unsigned long flags; - - spin_lock_irqsave(sdev->request_queue->queue_lock, flags); - sdev->scsi_dh_data = NULL; - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); - - sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", HP_SW_NAME); - - kfree(h); -} - static int __init hp_sw_init(void) { return scsi_register_device_handler(&hp_sw_dh); diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 8b09528613d2..b46ace3d4bf0 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -827,36 +827,16 @@ static bool rdac_match(struct scsi_device *sdev) return false; } -static int rdac_bus_attach(struct scsi_device *sdev); -static void rdac_bus_detach(struct scsi_device *sdev); - -static struct scsi_device_handler rdac_dh = { - .name = RDAC_NAME, - .module = THIS_MODULE, - .prep_fn = rdac_prep_fn, - .check_sense = rdac_check_sense, - .attach = rdac_bus_attach, - .detach = rdac_bus_detach, - .activate = rdac_activate, - .match = rdac_match, -}; - -static int rdac_bus_attach(struct scsi_device *sdev) +static struct scsi_dh_data *rdac_bus_attach(struct scsi_device *sdev) { struct rdac_dh_data *h; - unsigned long flags; int err; char array_name[ARRAY_LABEL_LEN]; char array_id[UNIQUE_ID_LEN]; h = kzalloc(sizeof(*h) , GFP_KERNEL); - if (!h) { - sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n", - RDAC_NAME); - return -ENOMEM; - } - - h->dh_data.scsi_dh = &rdac_dh; + if (!h) + return ERR_PTR(-ENOMEM); h->lun = UNINITIALIZED_LUN; h->state = RDAC_STATE_ACTIVE; @@ -876,16 +856,12 @@ static int rdac_bus_attach(struct scsi_device *sdev) if (err != SCSI_DH_OK) goto clean_ctlr; - spin_lock_irqsave(sdev->request_queue->queue_lock, flags); - sdev->scsi_dh_data = &h->dh_data; - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); - sdev_printk(KERN_NOTICE, sdev, "%s: LUN %d (%s) (%s)\n", RDAC_NAME, h->lun, mode[(int)h->mode], lun_state[(int)h->lun_state]); - return 0; + return &h->dh_data; clean_ctlr: spin_lock(&list_lock); @@ -894,32 +870,33 @@ static int rdac_bus_attach(struct scsi_device *sdev) failed: kfree(h); - sdev_printk(KERN_ERR, sdev, "%s: not attached\n", - RDAC_NAME); - return -EINVAL; + return ERR_PTR(-EINVAL); } static void rdac_bus_detach( struct scsi_device *sdev ) { struct rdac_dh_data *h = get_rdac_data(sdev); - unsigned long flags; if (h->ctlr && h->ctlr->ms_queued) flush_workqueue(kmpath_rdacd); - spin_lock_irqsave(sdev->request_queue->queue_lock, flags); - sdev->scsi_dh_data = NULL; - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); - spin_lock(&list_lock); if (h->ctlr) kref_put(&h->ctlr->kref, release_controller); spin_unlock(&list_lock); kfree(h); - sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", RDAC_NAME); } - +static struct scsi_device_handler rdac_dh = { + .name = RDAC_NAME, + .module = THIS_MODULE, + .prep_fn = rdac_prep_fn, + .check_sense = rdac_check_sense, + .attach = rdac_bus_attach, + .detach = rdac_bus_detach, + .activate = rdac_activate, + .match = rdac_match, +}; static int __init rdac_init(void) { diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 2601c97fd8b9..50d47e6e89d1 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -210,7 +210,7 @@ struct scsi_device_handler { struct module *module; const char *name; int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *); - int (*attach)(struct scsi_device *); + struct scsi_dh_data *(*attach)(struct scsi_device *); void (*detach)(struct scsi_device *); int (*activate)(struct scsi_device *, activate_complete, void *); int (*prep_fn)(struct scsi_device *, struct request *);