]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
[SCSI] zfcp: Register SCSI devices after successful fc_remote_port_add
authorChristof Schmitt <christof.schmitt@de.ibm.com>
Thu, 8 Jul 2010 07:53:07 +0000 (09:53 +0200)
committerJames Bottomley <James.Bottomley@suse.de>
Wed, 28 Jul 2010 14:46:38 +0000 (09:46 -0500)
When the successful return of an adisc is the final step to set the
port online, the registration of SCSI devices might be omitted. SCSI
devices that have been removed before (due to a short dev_loss_tmo
setting) might not be attached again.

The problem is that the registration of SCSI devices is done only
after erp has finished. The correct place would be after the call to
fc_remote_port_add to mimick the scan in the FC transport class.

Change the registration of SCSI devices to be triggered after the
fc_remote_port_add call. For the initial inquiry command to succeed,
the unit must also be open. If the unit reopen is still pending, the
inquiry command to the LUN will be deferred with DID_IMM_RETRY, so
there is no harm from this approach.

Reviewed-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/scsi/zfcp_sysfs.c

index e331df2122f7b2a8eeed71a656c602cebfbcb850..6e9c7f33e276e9d86453a01dcb5c3e69c7d6a999 100644 (file)
@@ -314,7 +314,7 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
        }
        retval = -EINVAL;
 
-       INIT_WORK(&unit->scsi_work, zfcp_scsi_scan);
+       INIT_WORK(&unit->scsi_work, zfcp_scsi_scan_work);
 
        spin_lock_init(&unit->latencies.lock);
        unit->latencies.write.channel.min = 0xFFFFFFFF;
index 5a71b73211df8cb03bb6457778e03af929cbf875..03cd6365ed047e3fcaa0861bad80db84ca6aca8f 100644 (file)
@@ -1192,12 +1192,6 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
 
        switch (act->action) {
        case ZFCP_ERP_ACTION_REOPEN_UNIT:
-               if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) {
-                       get_device(&unit->dev);
-                       if (scsi_queue_work(unit->port->adapter->scsi_host,
-                                           &unit->scsi_work) <= 0)
-                               put_device(&unit->dev);
-               }
                put_device(&unit->dev);
                break;
 
index 48a8f93b72f5d4cdfdcb49d0dac5e54b4017a97b..6abe2909e75b320ec7e2003fbd8654fbf54c0cb7 100644 (file)
@@ -159,7 +159,8 @@ extern void zfcp_scsi_rport_work(struct work_struct *);
 extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
 extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *);
 extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *);
-extern void zfcp_scsi_scan(struct work_struct *);
+extern void zfcp_scsi_scan(struct zfcp_unit *);
+extern void zfcp_scsi_scan_work(struct work_struct *);
 
 /* zfcp_sysfs.c */
 extern struct attribute_group zfcp_sysfs_unit_attrs;
index be5d2c60453d13c98950ecd4054333aca49448fd..153f69b26e7893aad0537c18bf001105d200371a 100644 (file)
@@ -524,6 +524,20 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
        }
 }
 
+static void zfcp_scsi_queue_unit_register(struct zfcp_port *port)
+{
+       struct zfcp_unit *unit;
+
+       read_lock_irq(&port->unit_list_lock);
+       list_for_each_entry(unit, &port->unit_list, list) {
+               get_device(&unit->dev);
+               if (scsi_queue_work(port->adapter->scsi_host,
+                                   &unit->scsi_work) <= 0)
+                       put_device(&unit->dev);
+       }
+       read_unlock_irq(&port->unit_list_lock);
+}
+
 static void zfcp_scsi_rport_register(struct zfcp_port *port)
 {
        struct fc_rport_identifiers ids;
@@ -548,6 +562,8 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
        rport->maxframe_size = port->maxframe_size;
        rport->supported_classes = port->supported_classes;
        port->rport = rport;
+
+       zfcp_scsi_queue_unit_register(port);
 }
 
 static void zfcp_scsi_rport_block(struct zfcp_port *port)
@@ -610,21 +626,26 @@ void zfcp_scsi_rport_work(struct work_struct *work)
        put_device(&port->dev);
 }
 
-
-void zfcp_scsi_scan(struct work_struct *work)
+/**
+ * zfcp_scsi_scan - Register LUN with SCSI midlayer
+ * @unit: The LUN/unit to register
+ */
+void zfcp_scsi_scan(struct zfcp_unit *unit)
 {
-       struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
-                                             scsi_work);
-       struct fc_rport *rport;
-
-       flush_work(&unit->port->rport_work);
-       rport = unit->port->rport;
+       struct fc_rport *rport = unit->port->rport;
 
        if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
                scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
                                 scsilun_to_int((struct scsi_lun *)
                                                &unit->fcp_lun), 0);
+}
+
+void zfcp_scsi_scan_work(struct work_struct *work)
+{
+       struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
+                                             scsi_work);
 
+       zfcp_scsi_scan(unit);
        put_device(&unit->dev);
 }
 
index f5f60698dc4c96c0d69ff09db3dc0221a11c92c3..205b9f8056e2290be54bc494bce0d87d5932a204 100644 (file)
@@ -275,7 +275,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
 
        zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL);
        zfcp_erp_wait(unit->port->adapter);
-       flush_work(&unit->scsi_work);
+       zfcp_scsi_scan(unit);
 out:
        put_device(&port->dev);
        return retval ? retval : (ssize_t) count;