[SCSI] scsi_sysfs: restore prep_fn when ULD is removed

A recent bug report:

http://bugzilla.kernel.org/show_bug.cgi?id=9674

Was caused because the ULDs now set their own prep functions, but
don't necessarily reset the prep function back to the SCSI default
when they are removed. This leads to panics if commands are sent to
the device after the module is removed because the prep_fn is still
pointing to the old module code. The fix for this is to implement a
bus remove method that resets the prep_fn pointer correctly before
calling the ULD specific driver remove method.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

+21 -1
+1 -1
drivers/scsi/scsi_lib.c
··· 1332 } 1333 EXPORT_SYMBOL(scsi_prep_return); 1334 1335 - static int scsi_prep_fn(struct request_queue *q, struct request *req) 1336 { 1337 struct scsi_device *sdev = q->queuedata; 1338 int ret = BLKPREP_KILL;
··· 1332 } 1333 EXPORT_SYMBOL(scsi_prep_return); 1334 1335 + int scsi_prep_fn(struct request_queue *q, struct request *req) 1336 { 1337 struct scsi_device *sdev = q->queuedata; 1338 int ret = BLKPREP_KILL;
+3
drivers/scsi/scsi_priv.h
··· 74 extern void scsi_free_queue(struct request_queue *q); 75 extern int scsi_init_queue(void); 76 extern void scsi_exit_queue(void); 77 78 /* scsi_proc.c */ 79 #ifdef CONFIG_SCSI_PROC_FS
··· 74 extern void scsi_free_queue(struct request_queue *q); 75 extern int scsi_init_queue(void); 76 extern void scsi_exit_queue(void); 77 + struct request_queue; 78 + struct request; 79 + extern int scsi_prep_fn(struct request_queue *, struct request *); 80 81 /* scsi_proc.c */ 82 #ifdef CONFIG_SCSI_PROC_FS
+17
drivers/scsi/scsi_sysfs.c
··· 373 return err; 374 } 375 376 struct bus_type scsi_bus_type = { 377 .name = "scsi", 378 .match = scsi_bus_match, 379 .uevent = scsi_bus_uevent, 380 .suspend = scsi_bus_suspend, 381 .resume = scsi_bus_resume, 382 }; 383 384 int scsi_sysfs_register(void)
··· 373 return err; 374 } 375 376 + static int scsi_bus_remove(struct device *dev) 377 + { 378 + struct device_driver *drv = dev->driver; 379 + struct scsi_device *sdev = to_scsi_device(dev); 380 + int err = 0; 381 + 382 + /* reset the prep_fn back to the default since the 383 + * driver may have altered it and it's being removed */ 384 + blk_queue_prep_rq(sdev->request_queue, scsi_prep_fn); 385 + 386 + if (drv && drv->remove) 387 + err = drv->remove(dev); 388 + 389 + return 0; 390 + } 391 + 392 struct bus_type scsi_bus_type = { 393 .name = "scsi", 394 .match = scsi_bus_match, 395 .uevent = scsi_bus_uevent, 396 .suspend = scsi_bus_suspend, 397 .resume = scsi_bus_resume, 398 + .remove = scsi_bus_remove, 399 }; 400 401 int scsi_sysfs_register(void)