scsi_dh: add 'rescan' callback
authorHannes Reinecke <hare@suse.de>
Fri, 19 Feb 2016 08:17:16 +0000 (09:17 +0100)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 24 Feb 2016 02:27:02 +0000 (21:27 -0500)
If a device needs to be rescanned the device_handler might need
to be rechecked, too.
So add a 'rescan' callback to the device handler and call it
upon scsi_rescan_device(). The rescan callback will be invoked
from the Unit Attention handling of ASC/ASCQ 3F 03
(INQUIRY DATA HAS CHANGED).

Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
include/scsi/scsi_dh.h

index 3d8a254..3d994aa 100644 (file)
@@ -1026,6 +1026,13 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req)
 
 }
 
+static void alua_rescan(struct scsi_device *sdev)
+{
+       struct alua_dh_data *h = sdev->handler_data;
+
+       alua_initialize(sdev, h);
+}
+
 /*
  * alua_bus_attach - Attach device handler
  * @sdev: device to be attached to
@@ -1086,6 +1093,7 @@ static struct scsi_device_handler alua_dh = {
        .prep_fn = alua_prep_fn,
        .check_sense = alua_check_sense,
        .activate = alua_activate,
+       .rescan = alua_rescan,
        .set_params = alua_set_params,
 };
 
index fa6b2c4..d46193a 100644 (file)
@@ -2699,6 +2699,7 @@ static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt)
                envp[idx++] = "SDEV_MEDIA_CHANGE=1";
                break;
        case SDEV_EVT_INQUIRY_CHANGE_REPORTED:
+               scsi_rescan_device(&sdev->sdev_gendev);
                envp[idx++] = "SDEV_UA=INQUIRY_DATA_HAS_CHANGED";
                break;
        case SDEV_EVT_CAPACITY_CHANGE_REPORTED:
index 420239c..97074c9 100644 (file)
@@ -43,6 +43,7 @@
 #include <scsi/scsi_devinfo.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport.h>
+#include <scsi/scsi_dh.h>
 #include <scsi/scsi_eh.h>
 
 #include "scsi_priv.h"
@@ -1524,9 +1525,14 @@ EXPORT_SYMBOL(scsi_add_device);
 
 void scsi_rescan_device(struct device *dev)
 {
+       struct scsi_device *sdev = to_scsi_device(dev);
+
        device_lock(dev);
 
-       scsi_attach_vpd(to_scsi_device(dev));
+       scsi_attach_vpd(sdev);
+
+       if (sdev->handler && sdev->handler->rescan)
+               sdev->handler->rescan(sdev);
 
        if (dev->driver && try_module_get(dev->driver->owner)) {
                struct scsi_driver *drv = to_scsi_driver(dev->driver);
index 7e184c6..c7bba2b 100644 (file)
@@ -71,6 +71,7 @@ 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 *);
+       void (*rescan)(struct scsi_device *);
 };
 
 #ifdef CONFIG_SCSI_DH