zfcp_erp.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,360 行 · 第 1/5 页
C
2,360 行
/* action must be dequeued (here to allow for further ones) */ zfcp_erp_action_dequeue(erp_action); /* * put this target through the erp mill again if someone has * requested to change the status of a target being online * to offline or the other way around * (old retval is preserved if nothing has to be done here) */ retval = zfcp_erp_strategy_statechange(action, status, adapter, port, unit, retval); /* * leave if target is in permanent error state or if * action is repeated in order to process state change */ if (retval == ZFCP_ERP_EXIT) { debug_text_event(adapter->erp_dbf, 2, "a_st_exit"); goto unlock; } /* trigger follow up actions */ zfcp_erp_strategy_followup_actions(action, adapter, port, unit, retval); unlock: write_unlock(&adapter->erp_lock); read_unlock_irqrestore(&zfcp_data.config_lock, flags); if (retval != ZFCP_ERP_CONTINUES) zfcp_erp_action_cleanup(action, adapter, port, unit, retval); /* * a few tasks remain when the erp queues are empty * (don't do that if the last action evaluated was dismissed * since this clearly indicates that there is more to come) : * - close the name server port if it is open yet * (enqueues another [probably] final action) * - otherwise, wake up whoever wants to be woken when we are * done with erp */ if (retval != ZFCP_ERP_DISMISSED) zfcp_erp_strategy_check_queues(adapter); debug_text_event(adapter->erp_dbf, 6, "a_st_done"); return retval;}/* * function: * * purpose: * * returns: ZFCP_ERP_DISMISSED - if action has been dismissed * retval - otherwise */static intzfcp_erp_strategy_check_action(struct zfcp_erp_action *erp_action, int retval){ struct zfcp_adapter *adapter = erp_action->adapter; zfcp_erp_strategy_check_fsfreq(erp_action); debug_event(adapter->erp_dbf, 5, &erp_action->action, sizeof (int)); if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) { debug_text_event(adapter->erp_dbf, 3, "a_stcd_dis"); zfcp_erp_action_dequeue(erp_action); retval = ZFCP_ERP_DISMISSED; } else debug_text_event(adapter->erp_dbf, 5, "a_stcd_nodis"); return retval;}/* * function: * * purpose: * * returns: */static intzfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action){ int retval = ZFCP_ERP_FAILED; struct zfcp_adapter *adapter = erp_action->adapter; /* * try to execute/continue action as far as possible, * note: no lock in subsequent strategy routines * (this allows these routine to call schedule, e.g. * kmalloc with such flags or qdio_initialize & friends) * Note: in case of timeout, the seperate strategies will fail * anyhow. No need for a special action. Even worse, a nameserver * failure would not wake up waiting ports without the call. */ switch (erp_action->action) { case ZFCP_ERP_ACTION_REOPEN_ADAPTER: retval = zfcp_erp_adapter_strategy(erp_action); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: retval = zfcp_erp_port_forced_strategy(erp_action); break; 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); ZFCP_LOG_NORMAL("port erp failed on port 0x%016Lx on adapter %s\n", port->wwpn, zfcp_get_busid_by_port(port)); 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));}/** * zfcp_erp_scsi_add_device * @data: pointer to a struct zfcp_unit * * Registers a logical unit with the SCSI stack. */static voidzfcp_erp_scsi_add_device(void *data){ struct { struct zfcp_unit *unit; struct work_struct work; } *p; p = data; scsi_add_device(p->unit->port->adapter->scsi_host, 0, p->unit->port->scsi_id, p->unit->scsi_lun); atomic_set(&p->unit->scsi_add_work, 0); wake_up(&p->unit->scsi_add_wq); zfcp_unit_put(p->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 intzfcp_erp_schedule_work(struct zfcp_unit *unit){ struct { struct zfcp_unit * unit; struct work_struct work; } *p; if (atomic_compare_and_swap(0, 1, &unit->scsi_add_work)) return 0; if ((p = kmalloc(sizeof(*p), GFP_KERNEL)) == NULL) { ZFCP_LOG_NORMAL("error: registration at SCSI stack failed for " "unit 0x%016Lx on port 0x%016Lx on " "adapter %s\n", unit->fcp_lun, unit->port->wwpn, zfcp_get_busid_by_unit(unit)); atomic_set(&unit->scsi_add_work, 0); return -ENOMEM; } zfcp_unit_get(unit); memset(p, 0, sizeof(*p)); INIT_WORK(&p->work, zfcp_erp_scsi_add_device, p); p->unit = unit; schedule_work(&p->work); return 0;}/* * 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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?