📄 zfcp_erp.c
字号:
kfree(send_els->resp); kfree(send_els);}/** * zfcp_test_link - lightweight link test procedure * @port: port to be tested * * Test status of a link to a remote port using the ELS command ADISC. */intzfcp_test_link(struct zfcp_port *port){ int retval; zfcp_port_get(port); retval = zfcp_erp_adisc(port); if (retval != 0) { zfcp_port_put(port); ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx " "on adapter %s\n ", port->wwpn, zfcp_get_busid_by_port(port)); retval = zfcp_erp_port_forced_reopen(port, 0); if (retval != 0) { ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx " "on adapter %s failed\n", port->wwpn, zfcp_get_busid_by_port(port)); retval = -EPERM; } } return retval;}/* * function: * * purpose: called if a port failed to be opened normally * initiates Forced Reopen recovery which is done * asynchronously * * returns: 0 - initiated action succesfully * <0 - failed to initiate action */static intzfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask){ int retval; struct zfcp_adapter *adapter = port->adapter; debug_text_event(adapter->erp_dbf, 5, "pf_ro"); debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); ZFCP_LOG_DEBUG("forced reopen of port 0x%016Lx on adapter %s\n", port->wwpn, zfcp_get_busid_by_port(port)); zfcp_erp_port_block(port, clear_mask); if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { ZFCP_LOG_DEBUG("skipped forced reopen of failed port 0x%016Lx " "on adapter %s\n", port->wwpn, zfcp_get_busid_by_port(port)); debug_text_event(adapter->erp_dbf, 5, "pf_ro_f"); debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); retval = -EIO; goto out; } retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, port->adapter, port, NULL); out: return retval;}/* * function: * * purpose: Wrappper for zfcp_erp_port_forced_reopen_internal * used to ensure the correct locking * * returns: 0 - initiated action succesfully * <0 - failed to initiate action */intzfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask){ int retval; unsigned long flags; struct zfcp_adapter *adapter; adapter = port->adapter; read_lock_irqsave(&zfcp_data.config_lock, flags); write_lock(&adapter->erp_lock); retval = zfcp_erp_port_forced_reopen_internal(port, clear_mask); write_unlock(&adapter->erp_lock); read_unlock_irqrestore(&zfcp_data.config_lock, flags); return retval;}/* * function: * * purpose: called if a port is to be opened * initiates Reopen recovery which is done * asynchronously * * returns: 0 - initiated action succesfully * <0 - failed to initiate action */static intzfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask){ int retval; struct zfcp_adapter *adapter = port->adapter; debug_text_event(adapter->erp_dbf, 5, "p_ro"); debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); ZFCP_LOG_DEBUG("reopen of port 0x%016Lx on adapter %s\n", port->wwpn, zfcp_get_busid_by_port(port)); zfcp_erp_port_block(port, clear_mask); if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { ZFCP_LOG_DEBUG("skipped reopen of failed port 0x%016Lx " "on adapter %s\n", port->wwpn, zfcp_get_busid_by_port(port)); debug_text_event(adapter->erp_dbf, 5, "p_ro_f"); debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); /* ensure propagation of failed status to new devices */ zfcp_erp_port_failed(port); retval = -EIO; goto out; } retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, port->adapter, port, NULL); out: return retval;}/** * zfcp_erp_port_reopen - initiate reopen of a remote port * @port: port to be reopened * @clear_mask: specifies flags in port status to be cleared * Return: 0 on success, < 0 on error * * This is a wrappper function for zfcp_erp_port_reopen_internal. It ensures * correct locking. An error recovery task is initiated to do the reopen. * To wait for the completion of the reopen zfcp_erp_wait should be used. */intzfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask){ int retval; unsigned long flags; struct zfcp_adapter *adapter = port->adapter; read_lock_irqsave(&zfcp_data.config_lock, flags); write_lock(&adapter->erp_lock); retval = zfcp_erp_port_reopen_internal(port, clear_mask); write_unlock(&adapter->erp_lock); read_unlock_irqrestore(&zfcp_data.config_lock, flags); return retval;}/* * function: * * purpose: called if a unit is to be opened * initiates Reopen recovery which is done * asynchronously * * returns: 0 - initiated action succesfully * <0 - failed to initiate action */static intzfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask){ int retval; struct zfcp_adapter *adapter = unit->port->adapter; debug_text_event(adapter->erp_dbf, 5, "u_ro"); debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t)); ZFCP_LOG_DEBUG("reopen of unit 0x%016Lx on port 0x%016Lx " "on adapter %s\n", unit->fcp_lun, unit->port->wwpn, zfcp_get_busid_by_unit(unit)); zfcp_erp_unit_block(unit, clear_mask); if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status)) { ZFCP_LOG_DEBUG("skipped reopen of failed 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(adapter->erp_dbf, 5, "u_ro_f"); debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t)); retval = -EIO; goto out; } retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT, unit->port->adapter, unit->port, unit); out: return retval;}/** * zfcp_erp_unit_reopen - initiate reopen of a unit * @unit: unit to be reopened * @clear_mask: specifies flags in unit status to be cleared * Return: 0 on success, < 0 on error * * This is a wrappper for zfcp_erp_unit_reopen_internal. It ensures correct * locking. An error recovery task is initiated to do the reopen. * To wait for the completion of the reopen zfcp_erp_wait should be used. */intzfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask){ int retval; unsigned long flags; struct zfcp_adapter *adapter; struct zfcp_port *port; port = unit->port; adapter = port->adapter; read_lock_irqsave(&zfcp_data.config_lock, flags); write_lock(&adapter->erp_lock); retval = zfcp_erp_unit_reopen_internal(unit, clear_mask); write_unlock(&adapter->erp_lock); read_unlock_irqrestore(&zfcp_data.config_lock, flags); return retval;}/* * function: * * purpose: disable I/O, * return any open requests and clean them up, * aim: no pending and incoming I/O * * returns: */static voidzfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask){ debug_text_event(adapter->erp_dbf, 6, "a_bl"); zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, ZFCP_CLEAR);}/* * function: * * purpose: enable I/O * * returns: */static voidzfcp_erp_adapter_unblock(struct zfcp_adapter *adapter){ debug_text_event(adapter->erp_dbf, 6, "a_ubl"); atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);}/* * function: * * purpose: disable I/O, * return any open requests and clean them up, * aim: no pending and incoming I/O * * returns: */static voidzfcp_erp_port_block(struct zfcp_port *port, int clear_mask){ struct zfcp_adapter *adapter = port->adapter; debug_text_event(adapter->erp_dbf, 6, "p_bl"); debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t)); zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, ZFCP_CLEAR);}/* * function: * * purpose: enable I/O * * returns: */static voidzfcp_erp_port_unblock(struct zfcp_port *port){ struct zfcp_adapter *adapter = port->adapter; debug_text_event(adapter->erp_dbf, 6, "p_ubl"); debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t)); atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);}/* * function: * * purpose: disable I/O, * return any open requests and clean them up, * aim: no pending and incoming I/O * * returns: */static voidzfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask){ struct zfcp_adapter *adapter = unit->port->adapter; debug_text_event(adapter->erp_dbf, 6, "u_bl"); debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t)); zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask, ZFCP_CLEAR);}/* * function: * * purpose: enable I/O * * returns: */static voidzfcp_erp_unit_unblock(struct zfcp_unit *unit){ struct zfcp_adapter *adapter = unit->port->adapter; debug_text_event(adapter->erp_dbf, 6, "u_ubl"); debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t)); atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);}/* * function: * * purpose: * * returns: */static voidzfcp_erp_action_ready(struct zfcp_erp_action *erp_action){ struct zfcp_adapter *adapter = erp_action->adapter; debug_text_event(adapter->erp_dbf, 4, "a_ar"); debug_event(adapter->erp_dbf, 4, &erp_action->action, sizeof (int)); zfcp_erp_action_to_ready(erp_action); up(&adapter->erp_ready_sem);}/* * function: * * purpose: * * returns: <0 erp_action not found in any list * ZFCP_ERP_ACTION_READY erp_action is in ready list * ZFCP_ERP_ACTION_RUNNING erp_action is in running list * * locks: erp_lock must be held */static intzfcp_erp_action_exists(struct zfcp_erp_action *erp_action){ int retval = -EINVAL; struct list_head *entry; struct zfcp_erp_action *entry_erp_action; struct zfcp_adapter *adapter = erp_action->adapter; /* search in running list */ list_for_each(entry, &adapter->erp_running_head) { entry_erp_action = list_entry(entry, struct zfcp_erp_action, list); if (entry_erp_action == erp_action) { retval = ZFCP_ERP_ACTION_RUNNING; goto out; } } /* search in ready list */ list_for_each(entry, &adapter->erp_ready_head) { entry_erp_action = list_entry(entry, struct zfcp_erp_action, list); if (entry_erp_action == erp_action) { retval = ZFCP_ERP_ACTION_READY; goto out; } } out: return retval;}/* * purpose: checks current status of action (timed out, dismissed, ...) * and does appropriate preparations (dismiss fsf request, ...) * * locks: called under erp_lock (disabled interrupts) * * returns: 0 */static intzfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action){ int retval = 0; struct zfcp_fsf_req *fsf_req = NULL; struct zfcp_adapter *adapter = erp_action->adapter; if (erp_action->fsf_req) { /* take lock to ensure that request is not being deleted meanwhile */ spin_lock(&adapter->fsf_req_list_lock); /* check whether fsf req does still exist */ list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list) if (fsf_req == erp_action->fsf_req) break; if (fsf_req && (fsf_req->erp_action == erp_action)) { /* fsf_req still exists */ debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); debug_event(adapter->erp_dbf, 3, &fsf_req, sizeof (unsigned long)); /* dismiss fsf_req of timed out or dismissed erp_action */ if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED | ZFCP_STATUS_ERP_TIMEDOUT)) { debug_text_event(adapter->erp_dbf, 3, "a_ca_disreq"); fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; } if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { ZFCP_LOG_NORMAL("error: erp step timed out " "(action=%d, fsf_req=%p)\n ", erp_action->action, erp_action->fsf_req); } /* * If fsf_req is neither dismissed nor completed * then keep it running asynchronously and don't mess * with the association of erp_action and fsf_req. */ if (fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED | ZFCP_STATUS_FSFREQ_DISMISSED)) { /* forget about association between fsf_req and erp_action */ fsf_req->erp_action = NULL; erp_action->fsf_req = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -