static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) { struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; struct zfcp_unit *unit = act->unit; switch (act->action) { case ZFCP_ERP_ACTION_REOPEN_UNIT: zfcp_unit_put(unit); break; case ZFCP_ERP_ACTION_REOPEN_PORT: if (result == ZFCP_ERP_SUCCEEDED) zfcp_scsi_schedule_rport_register(port); /* fall through */ case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: zfcp_port_put(port); break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (result == ZFCP_ERP_SUCCEEDED) { register_service_level(&adapter->service_level); queue_work(adapter->work_queue, &adapter->scan_work); } else unregister_service_level(&adapter->service_level); zfcp_adapter_put(adapter); break; } }
static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) { struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; struct scsi_device *sdev = act->sdev; switch (act->action) { case ZFCP_ERP_ACTION_REOPEN_LUN: if (!(act->status & ZFCP_STATUS_ERP_NO_REF)) scsi_device_put(sdev); break; case ZFCP_ERP_ACTION_REOPEN_PORT: if (result == ZFCP_ERP_SUCCEEDED) zfcp_scsi_schedule_rport_register(port); case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: put_device(&port->dev); break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (result == ZFCP_ERP_SUCCEEDED) { register_service_level(&adapter->service_level); queue_work(adapter->work_queue, &adapter->scan_work); queue_work(adapter->work_queue, &adapter->ns_up_work); } else unregister_service_level(&adapter->service_level); kref_put(&adapter->ref, zfcp_adapter_release); break; } }
static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) { struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; struct zfcp_unit *unit = act->unit; switch (act->action) { case ZFCP_ERP_ACTION_REOPEN_UNIT: if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) { zfcp_unit_get(unit); if (scsi_queue_work(unit->port->adapter->scsi_host, &unit->scsi_work) <= 0) zfcp_unit_put(unit); } zfcp_unit_put(unit); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT: if (result == ZFCP_ERP_SUCCEEDED) zfcp_scsi_schedule_rport_register(port); zfcp_port_put(port); break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (result == ZFCP_ERP_SUCCEEDED) { register_service_level(&adapter->service_level); schedule_work(&adapter->scan_work); } else unregister_service_level(&adapter->service_level); zfcp_adapter_put(adapter); break; } }
/** * zfcp_erp_try_rport_unblock - unblock rport if no more/new recovery * @port: zfcp_port whose fc_rport we should try to unblock */ static void zfcp_erp_try_rport_unblock(struct zfcp_port *port) { unsigned long flags; struct zfcp_adapter *adapter = port->adapter; int port_status; struct Scsi_Host *shost = adapter->scsi_host; struct scsi_device *sdev; write_lock_irqsave(&adapter->erp_lock, flags); port_status = atomic_read(&port->status); if ((port_status & ZFCP_STATUS_COMMON_UNBLOCKED) == 0 || (port_status & (ZFCP_STATUS_COMMON_ERP_INUSE | ZFCP_STATUS_COMMON_ERP_FAILED)) != 0) { /* new ERP of severity >= port triggered elsewhere meanwhile or * local link down (adapter erp_failed but not clear unblock) */ zfcp_dbf_rec_run_lvl(4, "ertru_p", &port->erp_action); write_unlock_irqrestore(&adapter->erp_lock, flags); return; } spin_lock(shost->host_lock); __shost_for_each_device(sdev, shost) { struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev); int lun_status; if (zsdev->port != port) continue; /* LUN under port of interest */ lun_status = atomic_read(&zsdev->status); if ((lun_status & ZFCP_STATUS_COMMON_ERP_FAILED) != 0) continue; /* unblock rport despite failed LUNs */ /* LUN recovery not given up yet [maybe follow-up pending] */ if ((lun_status & ZFCP_STATUS_COMMON_UNBLOCKED) == 0 || (lun_status & ZFCP_STATUS_COMMON_ERP_INUSE) != 0) { /* LUN blocked: * not yet unblocked [LUN recovery pending] * or meanwhile blocked [new LUN recovery triggered] */ zfcp_dbf_rec_run_lvl(4, "ertru_l", &zsdev->erp_action); spin_unlock(shost->host_lock); write_unlock_irqrestore(&adapter->erp_lock, flags); return; } } /* now port has no child or all children have completed recovery, * and no ERP of severity >= port was meanwhile triggered elsewhere */ zfcp_scsi_schedule_rport_register(port); spin_unlock(shost->host_lock); write_unlock_irqrestore(&adapter->erp_lock, flags); }
static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) { struct zfcp_adapter *adapter = act->adapter; struct zfcp_port *port = act->port; struct scsi_device *sdev = act->sdev; switch (act->action) { case ZFCP_ERP_ACTION_REOPEN_LUN: if (!(act->status & ZFCP_STATUS_ERP_NO_REF)) scsi_device_put(sdev); break; case ZFCP_ERP_ACTION_REOPEN_PORT: /* This switch case might also happen after a forced reopen * was successfully done and thus overwritten with a new * non-forced reopen at `ersfs_2'. In this case, we must not * do the clean-up of the non-forced version. */ if (act->step != ZFCP_ERP_STEP_UNINITIALIZED) if (result == ZFCP_ERP_SUCCEEDED) zfcp_scsi_schedule_rport_register(port); /* fall through */ case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: put_device(&port->dev); break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (result == ZFCP_ERP_SUCCEEDED) { register_service_level(&adapter->service_level); zfcp_fc_conditional_port_scan(adapter); queue_work(adapter->work_queue, &adapter->ns_up_work); } else unregister_service_level(&adapter->service_level); kref_put(&adapter->ref, zfcp_adapter_release); break; } }