Beispiel #1
0
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;
	}
}
Beispiel #4
0
/**
 * 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);
}
Beispiel #5
0
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;
	}
}