zfcp_erp.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,341 行 · 第 1/5 页

C
2,341
字号
	case ZFCP_LS_RTV:		rtv = (struct zfcp_ls_rtv_acc*)resp;		ZFCP_LOG_INFO("RTV response from d_id 0x%08x to s_id "			      "0x%08x (R_A_TOV=%ds E_D_TOV=%d%cs)\n",			      port->d_id, port->adapter->s_id,			      rtv->r_a_tov, rtv->e_d_tov,			      rtv->qualifier &			      ZFCP_LS_RTV_E_D_TOV_FLAG ? 'n' : 'm');		break;	case ZFCP_LS_RLS:		rls = (struct zfcp_ls_rls_acc*)resp;		ZFCP_LOG_INFO("RLS response from d_id 0x%08x to s_id "			      "0x%08x (link_failure_count=%u, "			      "loss_of_sync_count=%u, "			      "loss_of_signal_count=%u, "			      "primitive_sequence_protocol_error=%u, "			      "invalid_transmition_word=%u, "			      "invalid_crc_count=%u)\n",			      port->d_id, port->adapter->s_id,			      rls->link_failure_count,			      rls->loss_of_sync_count,			      rls->loss_of_signal_count,			      rls->prim_seq_prot_error,			      rls->invalid_transmition_word,			      rls->invalid_crc_count);		break;	case ZFCP_LS_PDISC:		pdisc = (struct zfcp_ls_pdisc_acc*)resp;		ZFCP_LOG_INFO("PDISC response from d_id 0x%08x to s_id "			      "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "			      "vendor='%-16s')\n", port->d_id,			      port->adapter->s_id, pdisc->wwpn,			      pdisc->wwnn, pdisc->vendor_version);		break;	case ZFCP_LS_ADISC:		adisc = (struct zfcp_ls_adisc_acc*)resp;		ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id "			      "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "			      "hard_nport_id=0x%08x, "			      "nport_id=0x%08x)\n", port->d_id,			      port->adapter->s_id, adisc->wwpn,			      adisc->wwnn, adisc->hard_nport_id,			      adisc->nport_id);		/* FIXME: set wwnn in during open port */		if (port->wwnn == 0)			port->wwnn = adisc->wwnn;		break;	} out:	__free_pages(send_els->req->page, 0);	kfree(send_els->req);	kfree(send_els->resp);	kfree(send_els);}/* * function:    zfcp_test_link * * purpose:     Test a status of a link to a remote port using the ELS command ADISC * * returns:     0       - Link is OK *              -EPERM  - Port forced reopen failed */intzfcp_test_link(struct zfcp_port *port){	int retval;	retval = zfcp_els(port, ZFCP_LS_ADISC);	if (retval != 0) {		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;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?