📄 zfcp_erp.c
字号:
case ZFCP_ERP_ACTION_REOPEN_PORT: retval = zfcp_erp_port_strategy(erp_action); break; case ZFCP_ERP_ACTION_REOPEN_UNIT: retval = zfcp_erp_unit_strategy(erp_action); break; default: debug_text_exception(adapter->erp_dbf, 1, "a_stda_bug"); debug_event(adapter->erp_dbf, 1, &erp_action->action, sizeof (int)); ZFCP_LOG_NORMAL("bug: unknown erp action requested on " "adapter %s (action=%d)\n", zfcp_get_busid_by_adapter(erp_action->adapter), erp_action->action); } return retval;}/* * function: * * purpose: triggers retry of this action after a certain amount of time * by means of timer provided by erp_action * * returns: ZFCP_ERP_CONTINUES - erp_action sleeps in erp running queue */static intzfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action){ int retval = ZFCP_ERP_CONTINUES; struct zfcp_adapter *adapter = erp_action->adapter; debug_text_event(adapter->erp_dbf, 6, "a_mwinit"); debug_event(adapter->erp_dbf, 6, &erp_action->action, sizeof (int)); init_timer(&erp_action->timer); erp_action->timer.function = zfcp_erp_memwait_handler; erp_action->timer.data = (unsigned long) erp_action; erp_action->timer.expires = jiffies + ZFCP_ERP_MEMWAIT_TIMEOUT; add_timer(&erp_action->timer); return retval;}/* * function: zfcp_erp_adapter_failed * * purpose: sets the adapter and all underlying devices to ERP_FAILED * */voidzfcp_erp_adapter_failed(struct zfcp_adapter *adapter){ zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); ZFCP_LOG_NORMAL("adapter erp failed on adapter %s\n", zfcp_get_busid_by_adapter(adapter)); debug_text_event(adapter->erp_dbf, 2, "a_afail");}/* * function: zfcp_erp_port_failed * * purpose: sets the port and all underlying devices to ERP_FAILED * */voidzfcp_erp_port_failed(struct zfcp_port *port){ zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status)) ZFCP_LOG_NORMAL("port erp failed (adapter %s, " "port d_id=0x%08x)\n", zfcp_get_busid_by_port(port), port->d_id); else ZFCP_LOG_NORMAL("port erp failed (adapter %s, wwpn=0x%016Lx)\n", zfcp_get_busid_by_port(port), port->wwpn); debug_text_event(port->adapter->erp_dbf, 2, "p_pfail"); debug_event(port->adapter->erp_dbf, 2, &port->wwpn, sizeof (wwn_t));}/* * function: zfcp_erp_unit_failed * * purpose: sets the unit to ERP_FAILED * */voidzfcp_erp_unit_failed(struct zfcp_unit *unit){ zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET); ZFCP_LOG_NORMAL("unit erp failed on unit 0x%016Lx on port 0x%016Lx " " on adapter %s\n", unit->fcp_lun, unit->port->wwpn, zfcp_get_busid_by_unit(unit)); debug_text_event(unit->port->adapter->erp_dbf, 2, "u_ufail"); debug_event(unit->port->adapter->erp_dbf, 2, &unit->fcp_lun, sizeof (fcp_lun_t));}/* * function: zfcp_erp_strategy_check_target * * purpose: increments the erp action count on the device currently in * recovery if the action failed or resets the count in case of * success. If a maximum count is exceeded the device is marked * as ERP_FAILED. * The 'blocked' state of a target which has been recovered * successfully is reset. * * returns: ZFCP_ERP_CONTINUES - action continues (not considered) * ZFCP_ERP_SUCCEEDED - action finished successfully * ZFCP_ERP_EXIT - action failed and will not continue */static intzfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, int result){ struct zfcp_adapter *adapter = erp_action->adapter; struct zfcp_port *port = erp_action->port; struct zfcp_unit *unit = erp_action->unit; debug_text_event(adapter->erp_dbf, 5, "a_stct_norm"); debug_event(adapter->erp_dbf, 5, &erp_action->action, sizeof (int)); debug_event(adapter->erp_dbf, 5, &result, sizeof (int)); switch (erp_action->action) { case ZFCP_ERP_ACTION_REOPEN_UNIT: result = zfcp_erp_strategy_check_unit(unit, result); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT: result = zfcp_erp_strategy_check_port(port, result); break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: result = zfcp_erp_strategy_check_adapter(adapter, result); break; } return result;}/* * function: * * purpose: * * returns: */static intzfcp_erp_strategy_statechange(int action, u32 status, struct zfcp_adapter *adapter, struct zfcp_port *port, struct zfcp_unit *unit, int retval){ debug_text_event(adapter->erp_dbf, 3, "a_stsc"); debug_event(adapter->erp_dbf, 3, &action, sizeof (int)); switch (action) { case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (zfcp_erp_strategy_statechange_detected(&adapter->status, status)) { zfcp_erp_adapter_reopen_internal(adapter, ZFCP_STATUS_COMMON_ERP_FAILED); retval = ZFCP_ERP_EXIT; } break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT: if (zfcp_erp_strategy_statechange_detected(&port->status, status)) { zfcp_erp_port_reopen_internal(port, ZFCP_STATUS_COMMON_ERP_FAILED); retval = ZFCP_ERP_EXIT; } break; case ZFCP_ERP_ACTION_REOPEN_UNIT: if (zfcp_erp_strategy_statechange_detected(&unit->status, status)) { zfcp_erp_unit_reopen_internal(unit, ZFCP_STATUS_COMMON_ERP_FAILED); retval = ZFCP_ERP_EXIT; } break; } return retval;}/* * function: * * purpose: * * returns: */static inline intzfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status){ return /* take it online */ (atomic_test_mask(ZFCP_STATUS_COMMON_RUNNING, target_status) && (ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status)) || /* take it offline */ (!atomic_test_mask(ZFCP_STATUS_COMMON_RUNNING, target_status) && !(ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status));}/* * function: * * purpose: * * returns: */static intzfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result){ debug_text_event(unit->port->adapter->erp_dbf, 5, "u_stct"); debug_event(unit->port->adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t)); switch (result) { case ZFCP_ERP_SUCCEEDED : atomic_set(&unit->erp_counter, 0); zfcp_erp_unit_unblock(unit); break; case ZFCP_ERP_FAILED : atomic_inc(&unit->erp_counter); if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) zfcp_erp_unit_failed(unit); break; case ZFCP_ERP_EXIT : /* nothing */ break; } if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status)) { zfcp_erp_unit_block(unit, 0); /* for ZFCP_ERP_SUCCEEDED */ result = ZFCP_ERP_EXIT; } return result;}/* * function: * * purpose: * * returns: */static intzfcp_erp_strategy_check_port(struct zfcp_port *port, int result){ debug_text_event(port->adapter->erp_dbf, 5, "p_stct"); debug_event(port->adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); switch (result) { case ZFCP_ERP_SUCCEEDED : atomic_set(&port->erp_counter, 0); zfcp_erp_port_unblock(port); break; case ZFCP_ERP_FAILED : atomic_inc(&port->erp_counter); if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) zfcp_erp_port_failed(port); break; case ZFCP_ERP_EXIT : /* nothing */ break; } if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { zfcp_erp_port_block(port, 0); /* for ZFCP_ERP_SUCCEEDED */ result = ZFCP_ERP_EXIT; } return result;}/* * function: * * purpose: * * returns: */static intzfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result){ debug_text_event(adapter->erp_dbf, 5, "a_stct"); switch (result) { case ZFCP_ERP_SUCCEEDED : atomic_set(&adapter->erp_counter, 0); zfcp_erp_adapter_unblock(adapter); break; case ZFCP_ERP_FAILED : atomic_inc(&adapter->erp_counter); if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) zfcp_erp_adapter_failed(adapter); break; case ZFCP_ERP_EXIT : /* nothing */ break; } if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) { zfcp_erp_adapter_block(adapter, 0); /* for ZFCP_ERP_SUCCEEDED */ result = ZFCP_ERP_EXIT; } return result;}/* * function: * * purpose: remaining things in good cases, * escalation in bad cases * * returns: */static intzfcp_erp_strategy_followup_actions(int action, struct zfcp_adapter *adapter, struct zfcp_port *port, struct zfcp_unit *unit, int status){ debug_text_event(adapter->erp_dbf, 5, "a_stfol"); debug_event(adapter->erp_dbf, 5, &action, sizeof (int)); /* initiate follow-up actions depending on success of finished action */ switch (action) { case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (status == ZFCP_ERP_SUCCEEDED) zfcp_erp_port_reopen_all_internal(adapter, 0); else zfcp_erp_adapter_reopen_internal(adapter, 0); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: if (status == ZFCP_ERP_SUCCEEDED) zfcp_erp_port_reopen_internal(port, 0); else zfcp_erp_adapter_reopen_internal(adapter, 0); break; case ZFCP_ERP_ACTION_REOPEN_PORT: if (status == ZFCP_ERP_SUCCEEDED) zfcp_erp_unit_reopen_all_internal(port, 0); else zfcp_erp_port_forced_reopen_internal(port, 0); break; case ZFCP_ERP_ACTION_REOPEN_UNIT: if (status == ZFCP_ERP_SUCCEEDED) ; /* no further action */ else zfcp_erp_port_reopen_internal(unit->port, 0); break; } return 0;}/* * function: * * purpose: * * returns: */static intzfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter){ unsigned long flags; read_lock_irqsave(&zfcp_data.config_lock, flags); read_lock(&adapter->erp_lock); if (list_empty(&adapter->erp_ready_head) && list_empty(&adapter->erp_running_head)) { debug_text_event(adapter->erp_dbf, 4, "a_cq_wake"); atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); wake_up(&adapter->erp_done_wqh); } else debug_text_event(adapter->erp_dbf, 5, "a_cq_notempty"); read_unlock(&adapter->erp_lock); read_unlock_irqrestore(&zfcp_data.config_lock, flags); return 0;}/** * zfcp_erp_wait - wait for completion of error recovery on an adapter * @adapter: adapter for which to wait for completion of its error recovery * Return: 0 */intzfcp_erp_wait(struct zfcp_adapter *adapter){ int retval = 0; wait_event(adapter->erp_done_wqh, !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status)); return retval;}/* * function: zfcp_erp_modify_adapter_status * * purpose: * */voidzfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u32 mask, int set_or_clear){ struct zfcp_port *port; u32 common_mask = mask & ZFCP_COMMON_FLAGS; if (set_or_clear == ZFCP_SET) { atomic_set_mask(mask, &adapter->status); debug_text_event(adapter->erp_dbf, 3, "a_mod_as_s"); } else { atomic_clear_mask(mask, &adapter->status); if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) atomic_set(&adapter->erp_counter, 0); debug_text_event(adapter->erp_dbf, 3, "a_mod_as_c"); } debug_event(adapter->erp_dbf, 3, &mask, sizeof (u32)); /* Deal with all underlying devices, only pass common_mask */ if (common_mask) list_for_each_entry(port, &adapter->port_list_head, list) zfcp_erp_modify_port_status(port, common_mask, set_or_clear);}/* * function: zfcp_erp_modify_port_status * * purpose: sets the port and all underlying devices to ERP_FAILED * */voidzfcp_erp_modify_port_status(struct zfcp_port *port, u32 mask, int set_or_clear){ struct zfcp_unit *unit; u32 common_mask = mask & ZFCP_COMMON_FLAGS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -