From 1bab0de0274fbe8c8ac92179e6705584c55ed169 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 27 Aug 2015 14:16:54 +0200 Subject: dm-mpath, scsi_dh: don't let dm detach device handlers While allowing dm-mpath to attach device handlers is a functionality we need for backwards compatibility reason there is no reason to reference count them and detach them if dm-mpath stops using the device for some reason. If the device handler works for the given device it can just stay attached, and we can take the retain_hw_handler codepath. Signed-off-by: Christoph Hellwig Acked-by: Mike Snitzer Acked-by: Hannes Reinecke Signed-off-by: James Bottomley --- include/scsi/scsi_device.h | 1 - include/scsi/scsi_dh.h | 5 ----- 2 files changed, 6 deletions(-) (limited to 'include/scsi') diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 50c2a363bc8f..798d67994aeb 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -221,7 +221,6 @@ struct scsi_device_handler { struct scsi_dh_data { struct scsi_device_handler *scsi_dh; struct scsi_device *sdev; - struct kref kref; }; #define to_scsi_device(d) \ diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h index 620c723ee8ed..99c9196fe606 100644 --- a/include/scsi/scsi_dh.h +++ b/include/scsi/scsi_dh.h @@ -59,7 +59,6 @@ enum { extern int scsi_dh_activate(struct request_queue *, activate_complete, void *); extern int scsi_dh_handler_exist(const char *); extern int scsi_dh_attach(struct request_queue *, const char *); -extern void scsi_dh_detach(struct request_queue *); extern const char *scsi_dh_attached_handler_name(struct request_queue *, gfp_t); extern int scsi_dh_set_params(struct request_queue *, const char *); #else @@ -77,10 +76,6 @@ static inline int scsi_dh_attach(struct request_queue *req, const char *name) { return SCSI_DH_NOSYS; } -static inline void scsi_dh_detach(struct request_queue *q) -{ - return; -} static inline const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp) { -- cgit v1.2.3 From 566079c849cfe538e908c44ac11a9c4638db8f91 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 27 Aug 2015 14:16:55 +0200 Subject: dm-mpath, scsi_dh: request scsi_dh modules in scsi_dh, not dm-mpath This way we can reused the same code any attachment method, not just those requested from dm-mpath. [jejb: fixup checkpatch error] Signed-off-by: Christoph Hellwig Reviewed-by: Martin K. Petersen Reviewed-by: Hannes Reinecke Acked-by: Mike Snitzer Signed-off-by: James Bottomley --- drivers/md/dm-mpath.c | 6 ------ drivers/scsi/device_handler/scsi_dh.c | 36 ++++++++++++++++++----------------- include/scsi/scsi_dh.h | 5 ----- 3 files changed, 19 insertions(+), 28 deletions(-) (limited to 'include/scsi') diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index a9f58fdb5d69..5a67671a3973 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -725,12 +725,6 @@ static int parse_hw_handler(struct dm_arg_set *as, struct multipath *m) return 0; m->hw_handler_name = kstrdup(dm_shift_arg(as), GFP_KERNEL); - if (!try_then_request_module(scsi_dh_handler_exist(m->hw_handler_name), - "scsi_dh_%s", m->hw_handler_name)) { - ti->error = "unknown hardware handler type"; - ret = -EINVAL; - goto fail; - } if (hw_argc > 1) { char *p; diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c index 869b5bd1ad25..3dfef5b0d298 100644 --- a/drivers/scsi/device_handler/scsi_dh.c +++ b/drivers/scsi/device_handler/scsi_dh.c @@ -29,7 +29,7 @@ static DEFINE_SPINLOCK(list_lock); static LIST_HEAD(scsi_dh_list); -static struct scsi_device_handler *get_device_handler(const char *name) +static struct scsi_device_handler *__scsi_dh_lookup(const char *name) { struct scsi_device_handler *tmp, *found = NULL; @@ -44,6 +44,19 @@ static struct scsi_device_handler *get_device_handler(const char *name) return found; } +static struct scsi_device_handler *scsi_dh_lookup(const char *name) +{ + struct scsi_device_handler *dh; + + dh = __scsi_dh_lookup(name); + if (!dh) { + request_module(name); + dh = __scsi_dh_lookup(name); + } + + return dh; +} + /* * device_handler_match_function - Match a device handler to a device * @sdev - SCSI device to be tested @@ -158,7 +171,8 @@ store_dh_state(struct device *dev, struct device_attribute *attr, /* * Attach to a device handler */ - if (!(scsi_dh = get_device_handler(buf))) + scsi_dh = scsi_dh_lookup(buf); + if (!scsi_dh) return err; err = scsi_dh_handler_attach(sdev, scsi_dh); } else { @@ -322,8 +336,7 @@ static int scsi_dh_notifier_remove(struct device *dev, void *data) */ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh) { - - if (get_device_handler(scsi_dh->name)) + if (__scsi_dh_lookup(scsi_dh->name)) return -EBUSY; if (!scsi_dh->attach || !scsi_dh->detach) @@ -350,7 +363,7 @@ EXPORT_SYMBOL_GPL(scsi_register_device_handler); int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) { - if (!get_device_handler(scsi_dh->name)) + if (!__scsi_dh_lookup(scsi_dh->name)) return -ENODEV; bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, @@ -454,17 +467,6 @@ int scsi_dh_set_params(struct request_queue *q, const char *params) } EXPORT_SYMBOL_GPL(scsi_dh_set_params); -/* - * scsi_dh_handler_exist - Return TRUE(1) if a device handler exists for - * the given name. FALSE(0) otherwise. - * @name - name of the device handler. - */ -int scsi_dh_handler_exist(const char *name) -{ - return (get_device_handler(name) != NULL); -} -EXPORT_SYMBOL_GPL(scsi_dh_handler_exist); - /* * scsi_dh_attach - Attach device handler * @q - Request queue that is associated with the scsi_device @@ -478,7 +480,7 @@ int scsi_dh_attach(struct request_queue *q, const char *name) struct scsi_device_handler *scsi_dh; int err = 0; - scsi_dh = get_device_handler(name); + scsi_dh = scsi_dh_lookup(name); if (!scsi_dh) return -EINVAL; diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h index 99c9196fe606..966b921135b5 100644 --- a/include/scsi/scsi_dh.h +++ b/include/scsi/scsi_dh.h @@ -57,7 +57,6 @@ enum { }; #if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE) extern int scsi_dh_activate(struct request_queue *, activate_complete, void *); -extern int scsi_dh_handler_exist(const char *); extern int scsi_dh_attach(struct request_queue *, const char *); extern const char *scsi_dh_attached_handler_name(struct request_queue *, gfp_t); extern int scsi_dh_set_params(struct request_queue *, const char *); @@ -68,10 +67,6 @@ static inline int scsi_dh_activate(struct request_queue *req, fn(data, 0); return 0; } -static inline int scsi_dh_handler_exist(const char *name) -{ - return 0; -} static inline int scsi_dh_attach(struct request_queue *req, const char *name) { return SCSI_DH_NOSYS; -- cgit v1.2.3 From 086b91d052ebe4ead5d28021afe3bdfd70af15bf Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 27 Aug 2015 14:16:57 +0200 Subject: scsi_dh: integrate into the core SCSI code Stop building scsi_dh as a separate module and integrate it fully into the core SCSI code with explicit callouts at bus scan time. For now the callouts are placed at the same point as the old bus notifiers were called, but in the future we will be able to look at ALUA INQUIRY data earlier on. Note that this also means that the device handler modules need to be loaded by the time we scan the bus. The next patches will add support for autoloading device handlers at bus scan time to make sure they are always loaded if they are enabled in the kernel config. Signed-off-by: Christoph Hellwig Reviewed-by: Martin K. Petersen Reviewed-by: Hannes Reinecke Acked-by: Mike Snitzer Signed-off-by: James Bottomley --- drivers/scsi/Makefile | 1 + drivers/scsi/device_handler/Kconfig | 2 +- drivers/scsi/device_handler/Makefile | 1 - drivers/scsi/scsi_dh.c | 183 +++-------------------------------- drivers/scsi/scsi_priv.h | 9 ++ drivers/scsi/scsi_sysfs.c | 10 ++ include/scsi/scsi_dh.h | 2 +- 7 files changed, 34 insertions(+), 174 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 471d08791766..1a8c9b53fafa 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -172,6 +172,7 @@ scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o scsi_mod-y += scsi_trace.o scsi_logging.o scsi_mod-$(CONFIG_PM) += scsi_pm.o +scsi_mod-$(CONFIG_SCSI_DH) += scsi_dh.o hv_storvsc-y := storvsc_drv.o diff --git a/drivers/scsi/device_handler/Kconfig b/drivers/scsi/device_handler/Kconfig index 69abd0ad48e2..e5647d59224f 100644 --- a/drivers/scsi/device_handler/Kconfig +++ b/drivers/scsi/device_handler/Kconfig @@ -3,7 +3,7 @@ # menuconfig SCSI_DH - tristate "SCSI Device Handlers" + bool "SCSI Device Handlers" depends on SCSI default n help diff --git a/drivers/scsi/device_handler/Makefile b/drivers/scsi/device_handler/Makefile index e1d2ea083e15..09866c50fbb4 100644 --- a/drivers/scsi/device_handler/Makefile +++ b/drivers/scsi/device_handler/Makefile @@ -1,7 +1,6 @@ # # SCSI Device Handler # -obj-$(CONFIG_SCSI_DH) += scsi_dh.o obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o obj-$(CONFIG_SCSI_DH_HP_SW) += scsi_dh_hp_sw.o obj-$(CONFIG_SCSI_DH_EMC) += scsi_dh_emc.o diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c index 3de9b6767be4..f0dfdccc060e 100644 --- a/drivers/scsi/scsi_dh.c +++ b/drivers/scsi/scsi_dh.c @@ -57,15 +57,8 @@ static struct scsi_device_handler *scsi_dh_lookup(const char *name) return dh; } -/* - * device_handler_match_function - Match a device handler to a device - * @sdev - SCSI device to be tested - * - * Tests @sdev against the match function of all registered device_handler. - * Returns the found device handler or NULL if not found. - */ static struct scsi_device_handler * -device_handler_match_function(struct scsi_device *sdev) +device_handler_match(struct scsi_device *sdev) { struct scsi_device_handler *tmp_dh, *found_dh = NULL; @@ -80,29 +73,6 @@ device_handler_match_function(struct scsi_device *sdev) return found_dh; } -/* - * device_handler_match - Attach a device handler to a device - * @scsi_dh - The device handler to match against or NULL - * @sdev - SCSI device to be tested against @scsi_dh - * - * Tests @sdev against the device handler @scsi_dh or against - * all registered device_handler if @scsi_dh == NULL. - * Returns the found device handler or NULL if not found. - */ -static struct scsi_device_handler * -device_handler_match(struct scsi_device_handler *scsi_dh, - struct scsi_device *sdev) -{ - struct scsi_device_handler *found_dh; - - found_dh = device_handler_match_function(sdev); - - if (scsi_dh && found_dh != scsi_dh) - found_dh = NULL; - - return found_dh; -} - /* * scsi_dh_handler_attach - Attach a device handler to a device * @sdev - SCSI device the device handler should attach to @@ -212,119 +182,26 @@ static struct device_attribute scsi_dh_state_attr = __ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state, store_dh_state); -/* - * scsi_dh_sysfs_attr_add - Callback for scsi_init_dh - */ -static int scsi_dh_sysfs_attr_add(struct device *dev, void *data) +int scsi_dh_add_device(struct scsi_device *sdev) { - struct scsi_device *sdev; + struct scsi_device_handler *devinfo; int err; - if (!scsi_is_sdev_device(dev)) - return 0; - - sdev = to_scsi_device(dev); - - err = device_create_file(&sdev->sdev_gendev, - &scsi_dh_state_attr); - - return 0; -} - -/* - * scsi_dh_sysfs_attr_remove - Callback for scsi_exit_dh - */ -static int scsi_dh_sysfs_attr_remove(struct device *dev, void *data) -{ - struct scsi_device *sdev; - - if (!scsi_is_sdev_device(dev)) - return 0; - - sdev = to_scsi_device(dev); - - device_remove_file(&sdev->sdev_gendev, - &scsi_dh_state_attr); - - return 0; -} + err = device_create_file(&sdev->sdev_gendev, &scsi_dh_state_attr); + if (err) + return err; -/* - * scsi_dh_notifier - notifier chain callback - */ -static int scsi_dh_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct device *dev = data; - struct scsi_device *sdev; - int err = 0; - struct scsi_device_handler *devinfo = NULL; - - if (!scsi_is_sdev_device(dev)) - return 0; - - sdev = to_scsi_device(dev); - - if (action == BUS_NOTIFY_ADD_DEVICE) { - err = device_create_file(dev, &scsi_dh_state_attr); - /* don't care about err */ - devinfo = device_handler_match(NULL, sdev); - if (devinfo) - err = scsi_dh_handler_attach(sdev, devinfo); - } else if (action == BUS_NOTIFY_DEL_DEVICE) { - device_remove_file(dev, &scsi_dh_state_attr); - if (sdev->scsi_dh_data) - scsi_dh_handler_detach(sdev); - } + devinfo = device_handler_match(sdev); + if (devinfo) + err = scsi_dh_handler_attach(sdev, devinfo); return err; } -/* - * scsi_dh_notifier_add - Callback for scsi_register_device_handler - */ -static int scsi_dh_notifier_add(struct device *dev, void *data) +void scsi_dh_remove_device(struct scsi_device *sdev) { - struct scsi_device_handler *scsi_dh = data; - struct scsi_device *sdev; - - if (!scsi_is_sdev_device(dev)) - return 0; - - if (!get_device(dev)) - return 0; - - sdev = to_scsi_device(dev); - - if (device_handler_match(scsi_dh, sdev)) - scsi_dh_handler_attach(sdev, scsi_dh); - - put_device(dev); - - return 0; -} - -/* - * scsi_dh_notifier_remove - Callback for scsi_unregister_device_handler - */ -static int scsi_dh_notifier_remove(struct device *dev, void *data) -{ - struct scsi_device_handler *scsi_dh = data; - struct scsi_device *sdev; - - if (!scsi_is_sdev_device(dev)) - return 0; - - if (!get_device(dev)) - return 0; - - sdev = to_scsi_device(dev); - - if (sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh == scsi_dh) + if (sdev->scsi_dh_data) scsi_dh_handler_detach(sdev); - - put_device(dev); - - return 0; + device_remove_file(&sdev->sdev_gendev, &scsi_dh_state_attr); } /* @@ -346,7 +223,6 @@ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh) list_add(&scsi_dh->list, &scsi_dh_list); spin_unlock(&list_lock); - bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add); printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name); return SCSI_DH_OK; @@ -362,13 +238,9 @@ EXPORT_SYMBOL_GPL(scsi_register_device_handler); */ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) { - if (!__scsi_dh_lookup(scsi_dh->name)) return -ENODEV; - bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, - scsi_dh_notifier_remove); - spin_lock(&list_lock); list_del(&scsi_dh->list); spin_unlock(&list_lock); @@ -538,34 +410,3 @@ const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp) return handler_name; } EXPORT_SYMBOL_GPL(scsi_dh_attached_handler_name); - -static struct notifier_block scsi_dh_nb = { - .notifier_call = scsi_dh_notifier -}; - -static int __init scsi_dh_init(void) -{ - int r; - - r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb); - - if (!r) - bus_for_each_dev(&scsi_bus_type, NULL, NULL, - scsi_dh_sysfs_attr_add); - - return r; -} - -static void __exit scsi_dh_exit(void) -{ - bus_for_each_dev(&scsi_bus_type, NULL, NULL, - scsi_dh_sysfs_attr_remove); - bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb); -} - -module_init(scsi_dh_init); -module_exit(scsi_dh_exit); - -MODULE_DESCRIPTION("SCSI device handler"); -MODULE_AUTHOR("Chandra Seetharaman "); -MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index e3902fc66278..644bb7339b55 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -170,6 +170,15 @@ static inline void scsi_autopm_put_host(struct Scsi_Host *h) {} extern struct async_domain scsi_sd_pm_domain; extern struct async_domain scsi_sd_probe_domain; +/* scsi_dh.c */ +#ifdef CONFIG_SCSI_DH +int scsi_dh_add_device(struct scsi_device *sdev); +void scsi_dh_remove_device(struct scsi_device *sdev); +#else +static inline int scsi_dh_add_device(struct scsi_device *sdev) { return 0; } +static inline void scsi_dh_remove_device(struct scsi_device *sdev) { } +#endif + /* * internal scsi timeout functions: for use by mid-layer and transport * classes. diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 9ad41168d26d..b333389f248f 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1030,11 +1030,20 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) "failed to add device: %d\n", error); return error; } + + error = scsi_dh_add_device(sdev); + if (error) { + sdev_printk(KERN_INFO, sdev, + "failed to add device handler: %d\n", error); + return error; + } + device_enable_async_suspend(&sdev->sdev_dev); error = device_add(&sdev->sdev_dev); if (error) { sdev_printk(KERN_INFO, sdev, "failed to add class device: %d\n", error); + scsi_dh_remove_device(sdev); device_del(&sdev->sdev_gendev); return error; } @@ -1074,6 +1083,7 @@ void __scsi_remove_device(struct scsi_device *sdev) bsg_unregister_queue(sdev->request_queue); device_unregister(&sdev->sdev_dev); transport_remove_device(dev); + scsi_dh_remove_device(sdev); device_del(dev); } else put_device(&sdev->sdev_dev); diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h index 966b921135b5..3a37b4c45997 100644 --- a/include/scsi/scsi_dh.h +++ b/include/scsi/scsi_dh.h @@ -55,7 +55,7 @@ enum { SCSI_DH_NOSYS, SCSI_DH_DRIVER_MAX, }; -#if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE) +#ifdef CONFIG_SCSI_DH extern int scsi_dh_activate(struct request_queue *, activate_complete, void *); extern int scsi_dh_attach(struct request_queue *, const char *); extern const char *scsi_dh_attached_handler_name(struct request_queue *, gfp_t); -- cgit v1.2.3 From d95dbff2a41e934cd8789734b34dc591e78ba11c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 27 Aug 2015 14:16:58 +0200 Subject: scsi_dh: move device matching to the core code Add a single list of devices that need non-ALUA device handlers to the core scsi_dh code so that we can autoload the modules for them at probe time. While this is a little ugly in terms of architecture it actually significantly simplifies the code in addition to the new autoloading functionality. Signed-off-by: Christoph Hellwig Reviewed-by: Martin K. Petersen Reviewed-by: Hannes Reinecke Acked-by: Mike Snitzer Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_alua.c | 6 --- drivers/scsi/device_handler/scsi_dh_emc.c | 29 ---------- drivers/scsi/device_handler/scsi_dh_hp_sw.c | 30 ----------- drivers/scsi/device_handler/scsi_dh_rdac.c | 50 ----------------- drivers/scsi/scsi_dh.c | 84 ++++++++++++++++++++++------- include/scsi/scsi_device.h | 1 - 6 files changed, 66 insertions(+), 134 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 854b568b9931..ace2457747a7 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -819,11 +819,6 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req) } -static bool alua_match(struct scsi_device *sdev) -{ - return (scsi_device_tpgs(sdev) != 0); -} - /* * alua_bus_attach - Attach device handler * @sdev: device to be attached to @@ -877,7 +872,6 @@ static struct scsi_device_handler alua_dh = { .check_sense = alua_check_sense, .activate = alua_activate, .set_params = alua_set_params, - .match = alua_match, }; static int __init alua_init(void) diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index 6ed1caadbc6a..fd31e67e9f50 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c @@ -622,34 +622,6 @@ done: return result; } -static const struct { - char *vendor; - char *model; -} clariion_dev_list[] = { - {"DGC", "RAID"}, - {"DGC", "DISK"}, - {"DGC", "VRAID"}, - {NULL, NULL}, -}; - -static bool clariion_match(struct scsi_device *sdev) -{ - int i; - - if (scsi_device_tpgs(sdev)) - return false; - - for (i = 0; clariion_dev_list[i].vendor; i++) { - if (!strncmp(sdev->vendor, clariion_dev_list[i].vendor, - strlen(clariion_dev_list[i].vendor)) && - !strncmp(sdev->model, clariion_dev_list[i].model, - strlen(clariion_dev_list[i].model))) { - return true; - } - } - return false; -} - static struct scsi_dh_data *clariion_bus_attach(struct scsi_device *sdev) { struct clariion_dh_data *h; @@ -698,7 +670,6 @@ static struct scsi_device_handler clariion_dh = { .activate = clariion_activate, .prep_fn = clariion_prep_fn, .set_params = clariion_set_params, - .match = clariion_match, }; static int __init clariion_init(void) diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index 485d99544a15..1bf10d37289a 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c @@ -311,35 +311,6 @@ static int hp_sw_activate(struct scsi_device *sdev, return 0; } -static const struct { - char *vendor; - char *model; -} hp_sw_dh_data_list[] = { - {"COMPAQ", "MSA1000 VOLUME"}, - {"COMPAQ", "HSV110"}, - {"HP", "HSV100"}, - {"DEC", "HSG80"}, - {NULL, NULL}, -}; - -static bool hp_sw_match(struct scsi_device *sdev) -{ - int i; - - if (scsi_device_tpgs(sdev)) - return false; - - for (i = 0; hp_sw_dh_data_list[i].vendor; i++) { - if (!strncmp(sdev->vendor, hp_sw_dh_data_list[i].vendor, - strlen(hp_sw_dh_data_list[i].vendor)) && - !strncmp(sdev->model, hp_sw_dh_data_list[i].model, - strlen(hp_sw_dh_data_list[i].model))) { - return true; - } - } - return false; -} - static struct scsi_dh_data *hp_sw_bus_attach(struct scsi_device *sdev) { struct hp_sw_dh_data *h; @@ -379,7 +350,6 @@ static struct scsi_device_handler hp_sw_dh = { .detach = hp_sw_bus_detach, .activate = hp_sw_activate, .prep_fn = hp_sw_prep_fn, - .match = hp_sw_match, }; static int __init hp_sw_init(void) diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index b46ace3d4bf0..d89616fe3ffa 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -778,55 +778,6 @@ static int rdac_check_sense(struct scsi_device *sdev, return SCSI_RETURN_NOT_HANDLED; } -static const struct { - char *vendor; - char *model; -} rdac_dev_list[] = { - {"IBM", "1722"}, - {"IBM", "1724"}, - {"IBM", "1726"}, - {"IBM", "1742"}, - {"IBM", "1745"}, - {"IBM", "1746"}, - {"IBM", "1813"}, - {"IBM", "1814"}, - {"IBM", "1815"}, - {"IBM", "1818"}, - {"IBM", "3526"}, - {"SGI", "TP9"}, - {"SGI", "IS"}, - {"STK", "OPENstorage D280"}, - {"STK", "FLEXLINE 380"}, - {"SUN", "CSM"}, - {"SUN", "LCSM100"}, - {"SUN", "STK6580_6780"}, - {"SUN", "SUN_6180"}, - {"SUN", "ArrayStorage"}, - {"DELL", "MD3"}, - {"NETAPP", "INF-01-00"}, - {"LSI", "INF-01-00"}, - {"ENGENIO", "INF-01-00"}, - {NULL, NULL}, -}; - -static bool rdac_match(struct scsi_device *sdev) -{ - int i; - - if (scsi_device_tpgs(sdev)) - return false; - - for (i = 0; rdac_dev_list[i].vendor; i++) { - if (!strncmp(sdev->vendor, rdac_dev_list[i].vendor, - strlen(rdac_dev_list[i].vendor)) && - !strncmp(sdev->model, rdac_dev_list[i].model, - strlen(rdac_dev_list[i].model))) { - return true; - } - } - return false; -} - static struct scsi_dh_data *rdac_bus_attach(struct scsi_device *sdev) { struct rdac_dh_data *h; @@ -895,7 +846,6 @@ static struct scsi_device_handler rdac_dh = { .attach = rdac_bus_attach, .detach = rdac_bus_detach, .activate = rdac_activate, - .match = rdac_match, }; static int __init rdac_init(void) diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c index f0dfdccc060e..9c153309c96b 100644 --- a/drivers/scsi/scsi_dh.c +++ b/drivers/scsi/scsi_dh.c @@ -29,6 +29,67 @@ static DEFINE_SPINLOCK(list_lock); static LIST_HEAD(scsi_dh_list); +struct scsi_dh_blist { + const char *vendor; + const char *model; + const char *driver; +}; + +static const struct scsi_dh_blist scsi_dh_blist[] = { + {"DGC", "RAID", "clariion" }, + {"DGC", "DISK", "clariion" }, + {"DGC", "VRAID", "clariion" }, + + {"COMPAQ", "MSA1000 VOLUME", "hp_sw" }, + {"COMPAQ", "HSV110", "hp_sw" }, + {"HP", "HSV100", "hp_sw"}, + {"DEC", "HSG80", "hp_sw"}, + + {"IBM", "1722", "rdac", }, + {"IBM", "1724", "rdac", }, + {"IBM", "1726", "rdac", }, + {"IBM", "1742", "rdac", }, + {"IBM", "1745", "rdac", }, + {"IBM", "1746", "rdac", }, + {"IBM", "1813", "rdac", }, + {"IBM", "1814", "rdac", }, + {"IBM", "1815", "rdac", }, + {"IBM", "1818", "rdac", }, + {"IBM", "3526", "rdac", }, + {"SGI", "TP9", "rdac", }, + {"SGI", "IS", "rdac", }, + {"STK", "OPENstorage D280", "rdac", }, + {"STK", "FLEXLINE 380", "rdac", }, + {"SUN", "CSM", "rdac", }, + {"SUN", "LCSM100", "rdac", }, + {"SUN", "STK6580_6780", "rdac", }, + {"SUN", "SUN_6180", "rdac", }, + {"SUN", "ArrayStorage", "rdac", }, + {"DELL", "MD3", "rdac", }, + {"NETAPP", "INF-01-00", "rdac", }, + {"LSI", "INF-01-00", "rdac", }, + {"ENGENIO", "INF-01-00", "rdac", }, + {NULL, NULL, NULL }, +}; + +static const char * +scsi_dh_find_driver(struct scsi_device *sdev) +{ + const struct scsi_dh_blist *b; + + if (scsi_device_tpgs(sdev)) + return "alua"; + + for (b = scsi_dh_blist; b->vendor; b++) { + if (!strncmp(sdev->vendor, b->vendor, strlen(b->vendor)) && + !strncmp(sdev->model, b->model, strlen(b->model))) { + return b->driver; + } + } + return NULL; +} + + static struct scsi_device_handler *__scsi_dh_lookup(const char *name) { struct scsi_device_handler *tmp, *found = NULL; @@ -57,22 +118,6 @@ static struct scsi_device_handler *scsi_dh_lookup(const char *name) return dh; } -static struct scsi_device_handler * -device_handler_match(struct scsi_device *sdev) -{ - struct scsi_device_handler *tmp_dh, *found_dh = NULL; - - spin_lock(&list_lock); - list_for_each_entry(tmp_dh, &scsi_dh_list, list) { - if (tmp_dh->match && tmp_dh->match(sdev)) { - found_dh = tmp_dh; - break; - } - } - spin_unlock(&list_lock); - return found_dh; -} - /* * scsi_dh_handler_attach - Attach a device handler to a device * @sdev - SCSI device the device handler should attach to @@ -184,14 +229,17 @@ static struct device_attribute scsi_dh_state_attr = int scsi_dh_add_device(struct scsi_device *sdev) { - struct scsi_device_handler *devinfo; + struct scsi_device_handler *devinfo = NULL; + const char *drv; int err; err = device_create_file(&sdev->sdev_gendev, &scsi_dh_state_attr); if (err) return err; - devinfo = device_handler_match(sdev); + drv = scsi_dh_find_driver(sdev); + if (drv) + devinfo = scsi_dh_lookup(drv); if (devinfo) err = scsi_dh_handler_attach(sdev, devinfo); return err; diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 798d67994aeb..4d501b7baa9b 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -215,7 +215,6 @@ struct scsi_device_handler { int (*activate)(struct scsi_device *, activate_complete, void *); int (*prep_fn)(struct scsi_device *, struct request *); int (*set_params)(struct scsi_device *, const char *); - bool (*match)(struct scsi_device *); }; struct scsi_dh_data { -- cgit v1.2.3 From ee14c674e8fc57251223054fb52dc0ecfe711028 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 27 Aug 2015 14:16:59 +0200 Subject: scsi_dh: kill struct scsi_dh_data Add a ->handler and a ->handler_data field to struct scsi_device and kill this indirection. Also move struct scsi_device_handler to scsi_dh.h so that changes to it don't require rebuilding every SCSI LLDD. Signed-off-by: Christoph Hellwig Reviewed-by: Martin K. Petersen Reviewed-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_alua.c | 25 ++++------ drivers/scsi/device_handler/scsi_dh_emc.c | 29 +++++------ drivers/scsi/device_handler/scsi_dh_hp_sw.c | 25 ++++------ drivers/scsi/device_handler/scsi_dh_rdac.c | 30 +++++------- drivers/scsi/scsi_dh.c | 75 +++++++++++------------------ drivers/scsi/scsi_error.c | 6 +-- drivers/scsi/scsi_lib.c | 6 +-- include/scsi/scsi_device.h | 25 ++-------- include/scsi/scsi_dh.h | 17 +++++++ 9 files changed, 98 insertions(+), 140 deletions(-) (limited to 'include/scsi') diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index ace2457747a7..cc2773b5de68 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -62,7 +62,6 @@ #define ALUA_OPTIMIZE_STPG 1 struct alua_dh_data { - struct scsi_dh_data dh_data; int group_id; int rel_port; int tpgs; @@ -86,11 +85,6 @@ struct alua_dh_data { static char print_alua_state(int); static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *); -static inline struct alua_dh_data *get_alua_data(struct scsi_device *sdev) -{ - return container_of(sdev->scsi_dh_data, struct alua_dh_data, dh_data); -} - static int realloc_buffer(struct alua_dh_data *h, unsigned len) { if (h->buff && h->buff != h->inq) @@ -708,7 +702,7 @@ out: */ static int alua_set_params(struct scsi_device *sdev, const char *params) { - struct alua_dh_data *h = get_alua_data(sdev); + struct alua_dh_data *h = sdev->handler_data; unsigned int optimize = 0, argc; const char *p = params; int result = SCSI_DH_OK; @@ -746,7 +740,7 @@ MODULE_PARM_DESC(optimize_stpg, "Allow use of a non-optimized path, rather than static int alua_activate(struct scsi_device *sdev, activate_complete fn, void *data) { - struct alua_dh_data *h = get_alua_data(sdev); + struct alua_dh_data *h = sdev->handler_data; int err = SCSI_DH_OK; int stpg = 0; @@ -804,7 +798,7 @@ out: */ static int alua_prep_fn(struct scsi_device *sdev, struct request *req) { - struct alua_dh_data *h = get_alua_data(sdev); + struct alua_dh_data *h = sdev->handler_data; int ret = BLKPREP_OK; if (h->state == TPGS_STATE_TRANSITIONING) @@ -823,14 +817,14 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req) * alua_bus_attach - Attach device handler * @sdev: device to be attached to */ -static struct scsi_dh_data *alua_bus_attach(struct scsi_device *sdev) +static int 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); + return -ENOMEM; h->tpgs = TPGS_MODE_UNINITIALIZED; h->state = TPGS_STATE_OPTIMIZED; h->group_id = -1; @@ -843,11 +837,11 @@ static struct scsi_dh_data *alua_bus_attach(struct scsi_device *sdev) 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; + sdev->handler_data = h; + return 0; failed: kfree(h); - return ERR_PTR(-EINVAL); + return -EINVAL; } /* @@ -856,10 +850,11 @@ failed: */ static void alua_bus_detach(struct scsi_device *sdev) { - struct alua_dh_data *h = get_alua_data(sdev); + struct alua_dh_data *h = sdev->handler_data; if (h->buff && h->inq != h->buff) kfree(h->buff); + sdev->handler_data = NULL; kfree(h); } diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index fd31e67e9f50..e6fb97cb12f4 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c @@ -72,7 +72,6 @@ static const char * lun_state[] = }; struct clariion_dh_data { - struct scsi_dh_data dh_data; /* * Flags: * CLARIION_SHORT_TRESPASS @@ -114,13 +113,6 @@ struct clariion_dh_data { int current_sp; }; -static inline struct clariion_dh_data - *get_clariion_data(struct scsi_device *sdev) -{ - return container_of(sdev->scsi_dh_data, struct clariion_dh_data, - dh_data); -} - /* * Parse MODE_SELECT cmd reply. */ @@ -450,7 +442,7 @@ static int clariion_check_sense(struct scsi_device *sdev, static int clariion_prep_fn(struct scsi_device *sdev, struct request *req) { - struct clariion_dh_data *h = get_clariion_data(sdev); + struct clariion_dh_data *h = sdev->handler_data; int ret = BLKPREP_OK; if (h->lun_state != CLARIION_LUN_OWNED) { @@ -533,7 +525,7 @@ retry: static int clariion_activate(struct scsi_device *sdev, activate_complete fn, void *data) { - struct clariion_dh_data *csdev = get_clariion_data(sdev); + struct clariion_dh_data *csdev = sdev->handler_data; int result; result = clariion_send_inquiry(sdev, csdev); @@ -574,7 +566,7 @@ done: */ static int clariion_set_params(struct scsi_device *sdev, const char *params) { - struct clariion_dh_data *csdev = get_clariion_data(sdev); + struct clariion_dh_data *csdev = sdev->handler_data; unsigned int hr = 0, st = 0, argc; const char *p = params; int result = SCSI_DH_OK; @@ -622,14 +614,14 @@ done: return result; } -static struct scsi_dh_data *clariion_bus_attach(struct scsi_device *sdev) +static int clariion_bus_attach(struct scsi_device *sdev) { struct clariion_dh_data *h; int err; h = kzalloc(sizeof(*h) , GFP_KERNEL); if (!h) - return ERR_PTR(-ENOMEM); + return -ENOMEM; h->lun_state = CLARIION_LUN_UNINITIALIZED; h->default_sp = CLARIION_UNBOUND_LU; h->current_sp = CLARIION_UNBOUND_LU; @@ -647,18 +639,19 @@ static struct scsi_dh_data *clariion_bus_attach(struct scsi_device *sdev) CLARIION_NAME, h->current_sp + 'A', h->port, lun_state[h->lun_state], h->default_sp + 'A'); - return &h->dh_data; + + sdev->handler_data = h; + return 0; failed: kfree(h); - return ERR_PTR(-EINVAL); + return -EINVAL; } static void clariion_bus_detach(struct scsi_device *sdev) { - struct clariion_dh_data *h = get_clariion_data(sdev); - - kfree(h); + kfree(sdev->handler_data); + sdev->handler_data = NULL; } static struct scsi_device_handler clariion_dh = { diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index 1bf10d37289a..9406d5f4a3d3 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c @@ -38,7 +38,6 @@ #define HP_SW_PATH_PASSIVE 1 struct hp_sw_dh_data { - struct scsi_dh_data dh_data; unsigned char sense[SCSI_SENSE_BUFFERSIZE]; int path_state; int retries; @@ -50,11 +49,6 @@ struct hp_sw_dh_data { static int hp_sw_start_stop(struct hp_sw_dh_data *); -static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev) -{ - return container_of(sdev->scsi_dh_data, struct hp_sw_dh_data, dh_data); -} - /* * tur_done - Handle TEST UNIT READY return status * @sdev: sdev the command has been sent to @@ -267,7 +261,7 @@ static int hp_sw_start_stop(struct hp_sw_dh_data *h) static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req) { - struct hp_sw_dh_data *h = get_hp_sw_data(sdev); + struct hp_sw_dh_data *h = sdev->handler_data; int ret = BLKPREP_OK; if (h->path_state != HP_SW_PATH_ACTIVE) { @@ -292,7 +286,7 @@ static int hp_sw_activate(struct scsi_device *sdev, activate_complete fn, void *data) { int ret = SCSI_DH_OK; - struct hp_sw_dh_data *h = get_hp_sw_data(sdev); + struct hp_sw_dh_data *h = sdev->handler_data; ret = hp_sw_tur(sdev, h); @@ -311,14 +305,14 @@ static int hp_sw_activate(struct scsi_device *sdev, return 0; } -static struct scsi_dh_data *hp_sw_bus_attach(struct scsi_device *sdev) +static int 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); + return -ENOMEM; h->path_state = HP_SW_PATH_UNINITIALIZED; h->retries = HP_SW_RETRIES; h->sdev = sdev; @@ -330,17 +324,18 @@ static struct scsi_dh_data *hp_sw_bus_attach(struct scsi_device *sdev) 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; + + sdev->handler_data = h; + return 0; failed: kfree(h); - return ERR_PTR(-EINVAL); + return -EINVAL; } static void hp_sw_bus_detach( struct scsi_device *sdev ) { - struct hp_sw_dh_data *h = get_hp_sw_data(sdev); - - kfree(h); + kfree(sdev->handler_data); + sdev->handler_data = NULL; } static struct scsi_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 d89616fe3ffa..361358134315 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -181,7 +181,6 @@ struct c2_inquiry { }; struct rdac_dh_data { - struct scsi_dh_data dh_data; struct rdac_controller *ctlr; #define UNINITIALIZED_LUN (1 << 8) unsigned lun; @@ -260,11 +259,6 @@ do { \ sdev_printk(KERN_INFO, sdev, RDAC_NAME ": " f "\n", ## arg); \ } while (0); -static inline struct rdac_dh_data *get_rdac_data(struct scsi_device *sdev) -{ - return container_of(sdev->scsi_dh_data, struct rdac_dh_data, dh_data); -} - static struct request *get_rdac_req(struct scsi_device *sdev, void *buffer, unsigned buflen, int rw) { @@ -544,7 +538,7 @@ static int mode_select_handle_sense(struct scsi_device *sdev, { struct scsi_sense_hdr sense_hdr; int err = SCSI_DH_IO, ret; - struct rdac_dh_data *h = get_rdac_data(sdev); + struct rdac_dh_data *h = sdev->handler_data; ret = scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE, &sense_hdr); if (!ret) @@ -589,7 +583,7 @@ static void send_mode_select(struct work_struct *work) container_of(work, struct rdac_controller, ms_work); struct request *rq; struct scsi_device *sdev = ctlr->ms_sdev; - struct rdac_dh_data *h = get_rdac_data(sdev); + struct rdac_dh_data *h = sdev->handler_data; struct request_queue *q = sdev->request_queue; int err, retry_cnt = RDAC_RETRY_COUNT; struct rdac_queue_data *tmp, *qdata; @@ -648,7 +642,7 @@ static int queue_mode_select(struct scsi_device *sdev, if (!qdata) return SCSI_DH_RETRY; - qdata->h = get_rdac_data(sdev); + qdata->h = sdev->handler_data; qdata->callback_fn = fn; qdata->callback_data = data; @@ -667,7 +661,7 @@ static int queue_mode_select(struct scsi_device *sdev, static int rdac_activate(struct scsi_device *sdev, activate_complete fn, void *data) { - struct rdac_dh_data *h = get_rdac_data(sdev); + struct rdac_dh_data *h = sdev->handler_data; int err = SCSI_DH_OK; int act = 0; @@ -702,7 +696,7 @@ done: static int rdac_prep_fn(struct scsi_device *sdev, struct request *req) { - struct rdac_dh_data *h = get_rdac_data(sdev); + struct rdac_dh_data *h = sdev->handler_data; int ret = BLKPREP_OK; if (h->state != RDAC_STATE_ACTIVE) { @@ -716,7 +710,7 @@ static int rdac_prep_fn(struct scsi_device *sdev, struct request *req) static int rdac_check_sense(struct scsi_device *sdev, struct scsi_sense_hdr *sense_hdr) { - struct rdac_dh_data *h = get_rdac_data(sdev); + struct rdac_dh_data *h = sdev->handler_data; RDAC_LOG(RDAC_LOG_SENSE, sdev, "array %s, ctlr %d, " "I/O returned with sense %02x/%02x/%02x", @@ -778,7 +772,7 @@ static int rdac_check_sense(struct scsi_device *sdev, return SCSI_RETURN_NOT_HANDLED; } -static struct scsi_dh_data *rdac_bus_attach(struct scsi_device *sdev) +static int rdac_bus_attach(struct scsi_device *sdev) { struct rdac_dh_data *h; int err; @@ -787,7 +781,7 @@ static struct scsi_dh_data *rdac_bus_attach(struct scsi_device *sdev) h = kzalloc(sizeof(*h) , GFP_KERNEL); if (!h) - return ERR_PTR(-ENOMEM); + return -ENOMEM; h->lun = UNINITIALIZED_LUN; h->state = RDAC_STATE_ACTIVE; @@ -812,7 +806,8 @@ static struct scsi_dh_data *rdac_bus_attach(struct scsi_device *sdev) RDAC_NAME, h->lun, mode[(int)h->mode], lun_state[(int)h->lun_state]); - return &h->dh_data; + sdev->handler_data = h; + return 0; clean_ctlr: spin_lock(&list_lock); @@ -821,12 +816,12 @@ clean_ctlr: failed: kfree(h); - return ERR_PTR(-EINVAL); + return -EINVAL; } static void rdac_bus_detach( struct scsi_device *sdev ) { - struct rdac_dh_data *h = get_rdac_data(sdev); + struct rdac_dh_data *h = sdev->handler_data; if (h->ctlr && h->ctlr->ms_queued) flush_workqueue(kmpath_rdacd); @@ -835,6 +830,7 @@ static void rdac_bus_detach( struct scsi_device *sdev ) if (h->ctlr) kref_put(&h->ctlr->kref, release_controller); spin_unlock(&list_lock); + sdev->handler_data = NULL; kfree(h); } diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c index 9c153309c96b..33c1148ff3b5 100644 --- a/drivers/scsi/scsi_dh.c +++ b/drivers/scsi/scsi_dh.c @@ -126,26 +126,20 @@ static struct scsi_device_handler *scsi_dh_lookup(const char *name) static int scsi_dh_handler_attach(struct scsi_device *sdev, struct scsi_device_handler *scsi_dh) { - struct scsi_dh_data *d; + int error; if (!try_module_get(scsi_dh->module)) return -EINVAL; - 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)); + error = scsi_dh->attach(sdev); + if (error) { + sdev_printk(KERN_ERR, sdev, "%s: Attach failed (%d)\n", + scsi_dh->name, error); module_put(scsi_dh->module); - return PTR_ERR(d); - } - - d->scsi_dh = scsi_dh; - d->sdev = sdev; + } else + sdev->handler = scsi_dh; - spin_lock_irq(sdev->request_queue->queue_lock); - sdev->scsi_dh_data = d; - spin_unlock_irq(sdev->request_queue->queue_lock); - return 0; + return error; } /* @@ -154,17 +148,9 @@ static int scsi_dh_handler_attach(struct scsi_device *sdev, */ static void scsi_dh_handler_detach(struct scsi_device *sdev) { - struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data; - struct scsi_device_handler *scsi_dh = scsi_dh_data->scsi_dh; - - scsi_dh->detach(sdev); - - spin_lock_irq(sdev->request_queue->queue_lock); - sdev->scsi_dh_data = NULL; - spin_unlock_irq(sdev->request_queue->queue_lock); - - sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", scsi_dh->name); - module_put(scsi_dh->module); + sdev->handler->detach(sdev); + sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", sdev->handler->name); + module_put(sdev->handler->module); } /* @@ -182,7 +168,7 @@ store_dh_state(struct device *dev, struct device_attribute *attr, sdev->sdev_state == SDEV_DEL) return -ENODEV; - if (!sdev->scsi_dh_data) { + if (!sdev->handler) { /* * Attach to a device handler */ @@ -191,7 +177,6 @@ store_dh_state(struct device *dev, struct device_attribute *attr, return err; err = scsi_dh_handler_attach(sdev, scsi_dh); } else { - scsi_dh = sdev->scsi_dh_data->scsi_dh; if (!strncmp(buf, "detach", 6)) { /* * Detach from a device handler @@ -202,8 +187,8 @@ store_dh_state(struct device *dev, struct device_attribute *attr, /* * Activate a device handler */ - if (scsi_dh->activate) - err = scsi_dh->activate(sdev, NULL, NULL); + if (sdev->handler->activate) + err = sdev->handler->activate(sdev, NULL, NULL); else err = 0; } @@ -217,10 +202,10 @@ show_dh_state(struct device *dev, struct device_attribute *attr, char *buf) { struct scsi_device *sdev = to_scsi_device(dev); - if (!sdev->scsi_dh_data) + if (!sdev->handler) return snprintf(buf, 20, "detached\n"); - return snprintf(buf, 20, "%s\n", sdev->scsi_dh_data->scsi_dh->name); + return snprintf(buf, 20, "%s\n", sdev->handler->name); } static struct device_attribute scsi_dh_state_attr = @@ -247,7 +232,7 @@ int scsi_dh_add_device(struct scsi_device *sdev) void scsi_dh_remove_device(struct scsi_device *sdev) { - if (sdev->scsi_dh_data) + if (sdev->handler) scsi_dh_handler_detach(sdev); device_remove_file(&sdev->sdev_gendev, &scsi_dh_state_attr); } @@ -316,7 +301,6 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) int err = 0; unsigned long flags; struct scsi_device *sdev; - struct scsi_device_handler *scsi_dh = NULL; struct device *dev = NULL; spin_lock_irqsave(q->queue_lock, flags); @@ -329,10 +313,8 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) return err; } - if (sdev->scsi_dh_data) - scsi_dh = sdev->scsi_dh_data->scsi_dh; dev = get_device(&sdev->sdev_gendev); - if (!scsi_dh || !dev || + if (!sdev->handler || !dev || sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL) err = SCSI_DH_NOSYS; @@ -346,8 +328,8 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) goto out; } - if (scsi_dh->activate) - err = scsi_dh->activate(sdev, fn, data); + if (sdev->handler->activate) + err = sdev->handler->activate(sdev, fn, data); out: put_device(dev); return err; @@ -369,19 +351,18 @@ int scsi_dh_set_params(struct request_queue *q, const char *params) int err = -SCSI_DH_NOSYS; unsigned long flags; struct scsi_device *sdev; - struct scsi_device_handler *scsi_dh = NULL; spin_lock_irqsave(q->queue_lock, flags); sdev = q->queuedata; - if (sdev && sdev->scsi_dh_data) - scsi_dh = sdev->scsi_dh_data->scsi_dh; - if (scsi_dh && scsi_dh->set_params && get_device(&sdev->sdev_gendev)) + if (sdev->handler && + sdev->handler->set_params && + get_device(&sdev->sdev_gendev)) err = 0; spin_unlock_irqrestore(q->queue_lock, flags); if (err) return err; - err = scsi_dh->set_params(sdev, params); + err = sdev->handler->set_params(sdev, params); put_device(&sdev->sdev_gendev); return err; } @@ -413,8 +394,8 @@ int scsi_dh_attach(struct request_queue *q, const char *name) if (err) return err; - if (sdev->scsi_dh_data) { - if (sdev->scsi_dh_data->scsi_dh != scsi_dh) + if (sdev->handler) { + if (sdev->handler != scsi_dh) err = -EBUSY; goto out_put_device; } @@ -451,8 +432,8 @@ const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp) if (!sdev) return NULL; - if (sdev->scsi_dh_data) - handler_name = kstrdup(sdev->scsi_dh_data->scsi_dh->name, gfp); + if (sdev->handler) + handler_name = kstrdup(sdev->handler->name, gfp); put_device(&sdev->sdev_gendev); return handler_name; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 3aacd96d63f3..410911c31c67 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include "scsi_priv.h" @@ -464,11 +465,10 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) if (scsi_sense_is_deferred(&sshdr)) return NEEDS_RETRY; - if (sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh && - sdev->scsi_dh_data->scsi_dh->check_sense) { + if (sdev->handler && sdev->handler->check_sense) { int rc; - rc = sdev->scsi_dh_data->scsi_dh->check_sense(sdev, &sshdr); + rc = sdev->handler->check_sense(sdev, &sshdr); if (rc != SCSI_RETURN_NOT_HANDLED) return rc; /* handler does not care. Drop down to default handling */ diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 882864f5cbae..cbfc5990052b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -1248,9 +1249,8 @@ static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) { struct scsi_cmnd *cmd = req->special; - if (unlikely(sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh - && sdev->scsi_dh_data->scsi_dh->prep_fn)) { - int ret = sdev->scsi_dh_data->scsi_dh->prep_fn(sdev, req); + if (unlikely(sdev->handler && sdev->handler->prep_fn)) { + int ret = sdev->handler->prep_fn(sdev, req); if (ret != BLKPREP_OK) return ret; } diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 4d501b7baa9b..fe89d7cd67b9 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -196,32 +196,13 @@ struct scsi_device { struct execute_work ew; /* used to get process context on put */ struct work_struct requeue_work; - struct scsi_dh_data *scsi_dh_data; + struct scsi_device_handler *handler; + void *handler_data; + enum scsi_device_state sdev_state; unsigned long sdev_data[0]; } __attribute__((aligned(sizeof(unsigned long)))); -typedef void (*activate_complete)(void *, int); -struct scsi_device_handler { - /* Used by the infrastructure */ - struct list_head list; /* list of scsi_device_handlers */ - - /* Filled by the hardware handler */ - struct module *module; - const char *name; - int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *); - 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 *); - int (*set_params)(struct scsi_device *, const char *); -}; - -struct scsi_dh_data { - struct scsi_device_handler *scsi_dh; - struct scsi_device *sdev; -}; - #define to_scsi_device(d) \ container_of(d, struct scsi_device, sdev_gendev) #define class_to_sdev(d) \ diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h index 3a37b4c45997..85d731746834 100644 --- a/include/scsi/scsi_dh.h +++ b/include/scsi/scsi_dh.h @@ -55,6 +55,23 @@ enum { SCSI_DH_NOSYS, SCSI_DH_DRIVER_MAX, }; + +typedef void (*activate_complete)(void *, int); +struct scsi_device_handler { + /* Used by the infrastructure */ + struct list_head list; /* list of scsi_device_handlers */ + + /* Filled by the hardware handler */ + struct module *module; + const char *name; + int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *); + int (*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 *); + int (*set_params)(struct scsi_device *, const char *); +}; + #ifdef CONFIG_SCSI_DH extern int scsi_dh_activate(struct request_queue *, activate_complete, void *); extern int scsi_dh_attach(struct request_queue *, const char *); -- cgit v1.2.3