Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Acked-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: James Bottomley <JBottomley@Odin.com>

authored by

Christoph Hellwig and committed by
James Bottomley
086b91d0 daaa858b

+34 -174
+1
drivers/scsi/Makefile
··· 172 172 scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o 173 173 scsi_mod-y += scsi_trace.o scsi_logging.o 174 174 scsi_mod-$(CONFIG_PM) += scsi_pm.o 175 + scsi_mod-$(CONFIG_SCSI_DH) += scsi_dh.o 175 176 176 177 hv_storvsc-y := storvsc_drv.o 177 178
+1 -1
drivers/scsi/device_handler/Kconfig
··· 3 3 # 4 4 5 5 menuconfig SCSI_DH 6 - tristate "SCSI Device Handlers" 6 + bool "SCSI Device Handlers" 7 7 depends on SCSI 8 8 default n 9 9 help
-1
drivers/scsi/device_handler/Makefile
··· 1 1 # 2 2 # SCSI Device Handler 3 3 # 4 - obj-$(CONFIG_SCSI_DH) += scsi_dh.o 5 4 obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o 6 5 obj-$(CONFIG_SCSI_DH_HP_SW) += scsi_dh_hp_sw.o 7 6 obj-$(CONFIG_SCSI_DH_EMC) += scsi_dh_emc.o
+12 -171
drivers/scsi/scsi_dh.c
··· 57 57 return dh; 58 58 } 59 59 60 - /* 61 - * device_handler_match_function - Match a device handler to a device 62 - * @sdev - SCSI device to be tested 63 - * 64 - * Tests @sdev against the match function of all registered device_handler. 65 - * Returns the found device handler or NULL if not found. 66 - */ 67 60 static struct scsi_device_handler * 68 - device_handler_match_function(struct scsi_device *sdev) 61 + device_handler_match(struct scsi_device *sdev) 69 62 { 70 63 struct scsi_device_handler *tmp_dh, *found_dh = NULL; 71 64 ··· 70 77 } 71 78 } 72 79 spin_unlock(&list_lock); 73 - return found_dh; 74 - } 75 - 76 - /* 77 - * device_handler_match - Attach a device handler to a device 78 - * @scsi_dh - The device handler to match against or NULL 79 - * @sdev - SCSI device to be tested against @scsi_dh 80 - * 81 - * Tests @sdev against the device handler @scsi_dh or against 82 - * all registered device_handler if @scsi_dh == NULL. 83 - * Returns the found device handler or NULL if not found. 84 - */ 85 - static struct scsi_device_handler * 86 - device_handler_match(struct scsi_device_handler *scsi_dh, 87 - struct scsi_device *sdev) 88 - { 89 - struct scsi_device_handler *found_dh; 90 - 91 - found_dh = device_handler_match_function(sdev); 92 - 93 - if (scsi_dh && found_dh != scsi_dh) 94 - found_dh = NULL; 95 - 96 80 return found_dh; 97 81 } 98 82 ··· 182 212 __ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state, 183 213 store_dh_state); 184 214 185 - /* 186 - * scsi_dh_sysfs_attr_add - Callback for scsi_init_dh 187 - */ 188 - static int scsi_dh_sysfs_attr_add(struct device *dev, void *data) 215 + int scsi_dh_add_device(struct scsi_device *sdev) 189 216 { 190 - struct scsi_device *sdev; 217 + struct scsi_device_handler *devinfo; 191 218 int err; 192 219 193 - if (!scsi_is_sdev_device(dev)) 194 - return 0; 220 + err = device_create_file(&sdev->sdev_gendev, &scsi_dh_state_attr); 221 + if (err) 222 + return err; 195 223 196 - sdev = to_scsi_device(dev); 197 - 198 - err = device_create_file(&sdev->sdev_gendev, 199 - &scsi_dh_state_attr); 200 - 201 - return 0; 202 - } 203 - 204 - /* 205 - * scsi_dh_sysfs_attr_remove - Callback for scsi_exit_dh 206 - */ 207 - static int scsi_dh_sysfs_attr_remove(struct device *dev, void *data) 208 - { 209 - struct scsi_device *sdev; 210 - 211 - if (!scsi_is_sdev_device(dev)) 212 - return 0; 213 - 214 - sdev = to_scsi_device(dev); 215 - 216 - device_remove_file(&sdev->sdev_gendev, 217 - &scsi_dh_state_attr); 218 - 219 - return 0; 220 - } 221 - 222 - /* 223 - * scsi_dh_notifier - notifier chain callback 224 - */ 225 - static int scsi_dh_notifier(struct notifier_block *nb, 226 - unsigned long action, void *data) 227 - { 228 - struct device *dev = data; 229 - struct scsi_device *sdev; 230 - int err = 0; 231 - struct scsi_device_handler *devinfo = NULL; 232 - 233 - if (!scsi_is_sdev_device(dev)) 234 - return 0; 235 - 236 - sdev = to_scsi_device(dev); 237 - 238 - if (action == BUS_NOTIFY_ADD_DEVICE) { 239 - err = device_create_file(dev, &scsi_dh_state_attr); 240 - /* don't care about err */ 241 - devinfo = device_handler_match(NULL, sdev); 242 - if (devinfo) 243 - err = scsi_dh_handler_attach(sdev, devinfo); 244 - } else if (action == BUS_NOTIFY_DEL_DEVICE) { 245 - device_remove_file(dev, &scsi_dh_state_attr); 246 - if (sdev->scsi_dh_data) 247 - scsi_dh_handler_detach(sdev); 248 - } 224 + devinfo = device_handler_match(sdev); 225 + if (devinfo) 226 + err = scsi_dh_handler_attach(sdev, devinfo); 249 227 return err; 250 228 } 251 229 252 - /* 253 - * scsi_dh_notifier_add - Callback for scsi_register_device_handler 254 - */ 255 - static int scsi_dh_notifier_add(struct device *dev, void *data) 230 + void scsi_dh_remove_device(struct scsi_device *sdev) 256 231 { 257 - struct scsi_device_handler *scsi_dh = data; 258 - struct scsi_device *sdev; 259 - 260 - if (!scsi_is_sdev_device(dev)) 261 - return 0; 262 - 263 - if (!get_device(dev)) 264 - return 0; 265 - 266 - sdev = to_scsi_device(dev); 267 - 268 - if (device_handler_match(scsi_dh, sdev)) 269 - scsi_dh_handler_attach(sdev, scsi_dh); 270 - 271 - put_device(dev); 272 - 273 - return 0; 274 - } 275 - 276 - /* 277 - * scsi_dh_notifier_remove - Callback for scsi_unregister_device_handler 278 - */ 279 - static int scsi_dh_notifier_remove(struct device *dev, void *data) 280 - { 281 - struct scsi_device_handler *scsi_dh = data; 282 - struct scsi_device *sdev; 283 - 284 - if (!scsi_is_sdev_device(dev)) 285 - return 0; 286 - 287 - if (!get_device(dev)) 288 - return 0; 289 - 290 - sdev = to_scsi_device(dev); 291 - 292 - if (sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh == scsi_dh) 232 + if (sdev->scsi_dh_data) 293 233 scsi_dh_handler_detach(sdev); 294 - 295 - put_device(dev); 296 - 297 - return 0; 234 + device_remove_file(&sdev->sdev_gendev, &scsi_dh_state_attr); 298 235 } 299 236 300 237 /* ··· 223 346 list_add(&scsi_dh->list, &scsi_dh_list); 224 347 spin_unlock(&list_lock); 225 348 226 - bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add); 227 349 printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name); 228 350 229 351 return SCSI_DH_OK; ··· 238 362 */ 239 363 int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) 240 364 { 241 - 242 365 if (!__scsi_dh_lookup(scsi_dh->name)) 243 366 return -ENODEV; 244 - 245 - bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, 246 - scsi_dh_notifier_remove); 247 367 248 368 spin_lock(&list_lock); 249 369 list_del(&scsi_dh->list); ··· 410 538 return handler_name; 411 539 } 412 540 EXPORT_SYMBOL_GPL(scsi_dh_attached_handler_name); 413 - 414 - static struct notifier_block scsi_dh_nb = { 415 - .notifier_call = scsi_dh_notifier 416 - }; 417 - 418 - static int __init scsi_dh_init(void) 419 - { 420 - int r; 421 - 422 - r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb); 423 - 424 - if (!r) 425 - bus_for_each_dev(&scsi_bus_type, NULL, NULL, 426 - scsi_dh_sysfs_attr_add); 427 - 428 - return r; 429 - } 430 - 431 - static void __exit scsi_dh_exit(void) 432 - { 433 - bus_for_each_dev(&scsi_bus_type, NULL, NULL, 434 - scsi_dh_sysfs_attr_remove); 435 - bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb); 436 - } 437 - 438 - module_init(scsi_dh_init); 439 - module_exit(scsi_dh_exit); 440 - 441 - MODULE_DESCRIPTION("SCSI device handler"); 442 - MODULE_AUTHOR("Chandra Seetharaman <sekharan@us.ibm.com>"); 443 - MODULE_LICENSE("GPL");
+9
drivers/scsi/scsi_priv.h
··· 170 170 extern struct async_domain scsi_sd_pm_domain; 171 171 extern struct async_domain scsi_sd_probe_domain; 172 172 173 + /* scsi_dh.c */ 174 + #ifdef CONFIG_SCSI_DH 175 + int scsi_dh_add_device(struct scsi_device *sdev); 176 + void scsi_dh_remove_device(struct scsi_device *sdev); 177 + #else 178 + static inline int scsi_dh_add_device(struct scsi_device *sdev) { return 0; } 179 + static inline void scsi_dh_remove_device(struct scsi_device *sdev) { } 180 + #endif 181 + 173 182 /* 174 183 * internal scsi timeout functions: for use by mid-layer and transport 175 184 * classes.
+10
drivers/scsi/scsi_sysfs.c
··· 1030 1030 "failed to add device: %d\n", error); 1031 1031 return error; 1032 1032 } 1033 + 1034 + error = scsi_dh_add_device(sdev); 1035 + if (error) { 1036 + sdev_printk(KERN_INFO, sdev, 1037 + "failed to add device handler: %d\n", error); 1038 + return error; 1039 + } 1040 + 1033 1041 device_enable_async_suspend(&sdev->sdev_dev); 1034 1042 error = device_add(&sdev->sdev_dev); 1035 1043 if (error) { 1036 1044 sdev_printk(KERN_INFO, sdev, 1037 1045 "failed to add class device: %d\n", error); 1046 + scsi_dh_remove_device(sdev); 1038 1047 device_del(&sdev->sdev_gendev); 1039 1048 return error; 1040 1049 } ··· 1083 1074 bsg_unregister_queue(sdev->request_queue); 1084 1075 device_unregister(&sdev->sdev_dev); 1085 1076 transport_remove_device(dev); 1077 + scsi_dh_remove_device(sdev); 1086 1078 device_del(dev); 1087 1079 } else 1088 1080 put_device(&sdev->sdev_dev);
+1 -1
include/scsi/scsi_dh.h
··· 55 55 SCSI_DH_NOSYS, 56 56 SCSI_DH_DRIVER_MAX, 57 57 }; 58 - #if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE) 58 + #ifdef CONFIG_SCSI_DH 59 59 extern int scsi_dh_activate(struct request_queue *, activate_complete, void *); 60 60 extern int scsi_dh_attach(struct request_queue *, const char *); 61 61 extern const char *scsi_dh_attached_handler_name(struct request_queue *, gfp_t);