zfcp_erp.c
来自「linux 内核源代码」· C语言 代码 · 共 2,247 行 · 第 1/5 页
C
2,247 行
* 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%06x)\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;}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;}static 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));}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;}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;}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;}struct zfcp_erp_add_work { struct zfcp_unit *unit; struct work_struct work;};/** * zfcp_erp_scsi_scan * @data: pointer to a struct zfcp_erp_add_work * * Registers a logical unit with the SCSI stack. */static void zfcp_erp_scsi_scan(struct work_struct *work){ struct zfcp_erp_add_work *p = container_of(work, struct zfcp_erp_add_work, work); struct zfcp_unit *unit = p->unit; struct fc_rport *rport = unit->port->rport; scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, unit->scsi_lun, 0); atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); wake_up(&unit->scsi_scan_wq); zfcp_unit_put(unit); kfree(p);}/** * zfcp_erp_schedule_work * @unit: pointer to unit which should be registered with SCSI stack * * Schedules work which registers a unit with the SCSI stack */static voidzfcp_erp_schedule_work(struct zfcp_unit *unit){ struct zfcp_erp_add_work *p; p = kzalloc(sizeof(*p), GFP_KERNEL); if (!p) { ZFCP_LOG_NORMAL("error: Out of resources. Could not register " "the FCP-LUN 0x%Lx connected to " "the port with WWPN 0x%Lx connected to " "the adapter %s with the SCSI stack.\n", unit->fcp_lun, unit->port->wwpn, zfcp_get_busid_by_unit(unit)); return; } zfcp_unit_get(unit); atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); INIT_WORK(&p->work, zfcp_erp_scsi_scan); p->unit = unit; schedule_work(&p->work);}/* * 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: /* Nothing to do if status == ZFCP_ERP_SUCCEEDED */ if (status != ZFCP_ERP_SUCCEEDED) zfcp_erp_port_reopen_internal(unit->port, 0); break; } return 0;}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;}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; if (set_or_clear == ZFCP_SET) { atomic_set_mask(mask, &port->status); debug_text_event(port->adapter->erp_dbf, 3, "p_mod_ps_s"); } else { atomic_clear_mask(mask, &port->status); if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) atomic_set(&port->erp_counter, 0); debug_text_event(port->adapter->erp_dbf, 3, "p_mod_ps_c"); } debug_event(port->adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t)); debug_event(port->adapter->erp_dbf, 3, &mask, sizeof (u32)); /* Modify status of all underlying devices, only pass common mask */ if (common_mask) list_for_each_entry(unit, &port->unit_list_head, list) zfcp_erp_modify_unit_status(unit, common_mask, set_or_clear);}/* * function: zfcp_erp_modify_unit_status * * purpose: sets the unit to ERP_FAILED * */voidzfcp_erp_modify_unit_status(struct zfcp_unit *unit, u32 mask, int set_or_clear){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?