⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zfcp_erp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			}		} else {			debug_text_event(adapter->erp_dbf, 3, "a_ca_gonereq");			/*			 * even if this fsf_req has gone, forget about			 * association between erp_action and fsf_req			 */			erp_action->fsf_req = NULL;		}		spin_unlock(&adapter->fsf_req_list_lock);	} else		debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");	return retval;}/* * purpose:	generic handler for asynchronous events related to erp_action events *		(normal completion, time-out, dismissing, retry after *		low memory condition) * * note:	deletion of timer is not required (e.g. in case of a time-out), *		but a second try does no harm, *		we leave it in here to allow for greater simplification * * returns:	0 - there was an action to handle *		!0 - otherwise */static intzfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action,			      unsigned long set_mask){	int retval;	struct zfcp_adapter *adapter = erp_action->adapter;	if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) {		debug_text_event(adapter->erp_dbf, 2, "a_asyh_ex");		debug_event(adapter->erp_dbf, 2, &erp_action->action,			    sizeof (int));		if (!(set_mask & ZFCP_STATUS_ERP_TIMEDOUT))			del_timer(&erp_action->timer);		erp_action->status |= set_mask;		zfcp_erp_action_ready(erp_action);		retval = 0;	} else {		/* action is ready or gone - nothing to do */		debug_text_event(adapter->erp_dbf, 3, "a_asyh_gone");		debug_event(adapter->erp_dbf, 3, &erp_action->action,			    sizeof (int));		retval = 1;	}	return retval;}/* * purpose:	generic handler for asynchronous events related to erp_action *               events	(normal completion, time-out, dismissing, retry after *		low memory condition) * * note:	deletion of timer is not required (e.g. in case of a time-out), *		but a second try does no harm, *		we leave it in here to allow for greater simplification * * returns:	0 - there was an action to handle *		!0 - otherwise */intzfcp_erp_async_handler(struct zfcp_erp_action *erp_action,		       unsigned long set_mask){	struct zfcp_adapter *adapter = erp_action->adapter;	unsigned long flags;	int retval;	write_lock_irqsave(&adapter->erp_lock, flags);	retval = zfcp_erp_async_handler_nolock(erp_action, set_mask);	write_unlock_irqrestore(&adapter->erp_lock, flags);	return retval;}/* * purpose:	is called for erp_action which was slept waiting for *		memory becoming avaliable, *		will trigger that this action will be continued */static voidzfcp_erp_memwait_handler(unsigned long data){	struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;	struct zfcp_adapter *adapter = erp_action->adapter;	debug_text_event(adapter->erp_dbf, 2, "a_mwh");	debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));	zfcp_erp_async_handler(erp_action, 0);}/* * purpose:	is called if an asynchronous erp step timed out, *		action gets an appropriate flag and will be processed *		accordingly */static voidzfcp_erp_timeout_handler(unsigned long data){	struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;	struct zfcp_adapter *adapter = erp_action->adapter;	debug_text_event(adapter->erp_dbf, 2, "a_th");	debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));	zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT);}/* * purpose:	is called for an erp_action which needs to be ended *		though not being done, *		this is usually required if an higher is generated, *		action gets an appropriate flag and will be processed *		accordingly * * locks:	erp_lock held (thus we need to call another handler variant) */static intzfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action){	struct zfcp_adapter *adapter = erp_action->adapter;	debug_text_event(adapter->erp_dbf, 2, "a_adis");	debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));	zfcp_erp_async_handler_nolock(erp_action, ZFCP_STATUS_ERP_DISMISSED);	return 0;}intzfcp_erp_thread_setup(struct zfcp_adapter *adapter){	int retval = 0;	atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);	retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD);	if (retval < 0) {		ZFCP_LOG_NORMAL("error: creation of erp thread failed for "				"adapter %s\n",				zfcp_get_busid_by_adapter(adapter));		debug_text_event(adapter->erp_dbf, 5, "a_thset_fail");	} else {		wait_event(adapter->erp_thread_wqh,			   atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP,					    &adapter->status));		debug_text_event(adapter->erp_dbf, 5, "a_thset_ok");	}	return (retval < 0);}/* * function:	 * * purpose:	 * * returns: * * context:	process (i.e. proc-fs or rmmod/insmod) * * note:	The caller of this routine ensures that the specified *		adapter has been shut down and that this operation *		has been completed. Thus, there are no pending erp_actions *		which would need to be handled here. */intzfcp_erp_thread_kill(struct zfcp_adapter *adapter){	int retval = 0;	atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status);	up(&adapter->erp_ready_sem);	wait_event(adapter->erp_thread_wqh,		   !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP,				     &adapter->status));	atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,			  &adapter->status);	debug_text_event(adapter->erp_dbf, 5, "a_thki_ok");	return retval;}/* * purpose:	is run as a kernel thread, *		goes through list of error recovery actions of associated adapter *		and delegates single action to execution * * returns:	0 */static intzfcp_erp_thread(void *data){	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;	struct list_head *next;	struct zfcp_erp_action *erp_action;	unsigned long flags;	daemonize("zfcperp%s", zfcp_get_busid_by_adapter(adapter));	/* Block all signals */	siginitsetinv(&current->blocked, 0);	atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);	debug_text_event(adapter->erp_dbf, 5, "a_th_run");	wake_up(&adapter->erp_thread_wqh);	while (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,				 &adapter->status)) {		write_lock_irqsave(&adapter->erp_lock, flags);		next = adapter->erp_ready_head.prev;		write_unlock_irqrestore(&adapter->erp_lock, flags);		if (next != &adapter->erp_ready_head) {			erp_action =			    list_entry(next, struct zfcp_erp_action, list);			/*			 * process action (incl. [re]moving it			 * from 'ready' queue)			 */			zfcp_erp_strategy(erp_action);		}		/*		 * sleep as long as there is nothing to do, i.e.		 * no action in 'ready' queue to be processed and		 * thread is not to be killed		 */		down_interruptible(&adapter->erp_ready_sem);		debug_text_event(adapter->erp_dbf, 5, "a_th_woken");	}	atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);	debug_text_event(adapter->erp_dbf, 5, "a_th_stop");	wake_up(&adapter->erp_thread_wqh);	return 0;}/* * function:	 * * purpose:	drives single error recovery action and schedules higher and *		subordinate actions, if necessary * * returns:	ZFCP_ERP_CONTINUES	- action continues (asynchronously) *		ZFCP_ERP_SUCCEEDED	- action finished successfully (deqd) *		ZFCP_ERP_FAILED		- action finished unsuccessfully (deqd) *		ZFCP_ERP_EXIT		- action finished (dequeued), offline *		ZFCP_ERP_DISMISSED	- action canceled (dequeued) */static intzfcp_erp_strategy(struct zfcp_erp_action *erp_action){	int retval = 0;	struct zfcp_adapter *adapter = erp_action->adapter;	struct zfcp_port *port = erp_action->port;	struct zfcp_unit *unit = erp_action->unit;	int action = erp_action->action;	u32 status = erp_action->status;	unsigned long flags;	/* serialise dismissing, timing out, moving, enqueueing */	read_lock_irqsave(&zfcp_data.config_lock, flags);	write_lock(&adapter->erp_lock);	/* dequeue dismissed action and leave, if required */	retval = zfcp_erp_strategy_check_action(erp_action, retval);	if (retval == ZFCP_ERP_DISMISSED) {		debug_text_event(adapter->erp_dbf, 4, "a_st_dis1");		goto unlock;	}	/*	 * move action to 'running' queue before processing it	 * (to avoid a race condition regarding moving the	 * action to the 'running' queue and back)	 */	zfcp_erp_action_to_running(erp_action);	/*	 * try to process action as far as possible,	 * no lock to allow for blocking operations (kmalloc, qdio, ...),	 * afterwards the lock is required again for the following reasons:	 * - dequeueing of finished action and enqueueing of	 *   follow-up actions must be atomic so that any other	 *   reopen-routine does not believe there is nothing to do	 *   and that it is safe to enqueue something else,	 * - we want to force any control thread which is dismissing	 *   actions to finish this before we decide about	 *   necessary steps to be taken here further	 */	write_unlock(&adapter->erp_lock);	read_unlock_irqrestore(&zfcp_data.config_lock, flags);	retval = zfcp_erp_strategy_do_action(erp_action);	read_lock_irqsave(&zfcp_data.config_lock, flags);	write_lock(&adapter->erp_lock);	/*	 * check for dismissed status again to avoid follow-up actions,	 * failing of targets and so on for dismissed actions	 */	retval = zfcp_erp_strategy_check_action(erp_action, retval);	switch (retval) {	case ZFCP_ERP_DISMISSED:		/* leave since this action has ridden to its ancestors */		debug_text_event(adapter->erp_dbf, 6, "a_st_dis2");		goto unlock;	case ZFCP_ERP_NOMEM:		/* no memory to continue immediately, let it sleep */		if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) {			++adapter->erp_low_mem_count;			erp_action->status |= ZFCP_STATUS_ERP_LOWMEM;		}		/* This condition is true if there is no memory available		   for any erp_action on this adapter. This implies that there		   are no elements in the memory pool(s) left for erp_actions.		   This might happen if an erp_action that used a memory pool		   element was timed out.		 */		if (adapter->erp_total_count == adapter->erp_low_mem_count) {			debug_text_event(adapter->erp_dbf, 3, "a_st_lowmem");			ZFCP_LOG_NORMAL("error: no mempool elements available, "					"restarting I/O on adapter %s "					"to free mempool\n",					zfcp_get_busid_by_adapter(adapter));			zfcp_erp_adapter_reopen_internal(adapter, 0);		} else {		debug_text_event(adapter->erp_dbf, 2, "a_st_memw");		retval = zfcp_erp_strategy_memwait(erp_action);		}		goto unlock;	case ZFCP_ERP_CONTINUES:		/* leave since this action runs asynchronously */		debug_text_event(adapter->erp_dbf, 6, "a_st_cont");		if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {			--adapter->erp_low_mem_count;			erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;		}		goto unlock;	}	/* ok, finished action (whatever its result is) */	/* check for unrecoverable targets */	retval = zfcp_erp_strategy_check_target(erp_action, retval);	/* 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;

⌨️ 快捷键说明

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