Ejemplo n.º 1
0
/***********************************************************************
F* Function:     int wd_reset_mon_chain(int chainid) P*A*Z*
 *
P* Parameters:   int chainid
P*                - The id of the chain to reset
P*
P* Returnvalue:  int
P*                - 0 The chain was reset suiccessfully
P*                 <0 Errorcondition, which can be
P*                  -EINVAL The supplied id is unknown.
 *
Z* Intention:    This function resets a chain to its initial state.
Z*               The function is called through the ioctl() mechanism
Z*               to reset or trigger a chain or directly from other
Z*               kernel proper, as it is exported.
 *
D* Design:       [email protected]
C* Coding:       [email protected]
V* Verification: [email protected]
 ***********************************************************************/
int wd_reset_mon_chain(int chainid)
{
	monitored_chain_t *entry;
	int result = 0;

	debugk("%s: WD monitor reset for id %d\n", __FUNCTION__, chainid);

	spin_lock(&mon_lock);

	if ((entry = find_mon_chain_by_chainid(chainid)) == NULL) {
		result = -EINVAL;
		goto out;
	}
	entry->escalation = 0;
	entry->expires = jiffies + HZ * entry->timer_count[0];
	list_del(&entry->list);
	insert_mon_chain(entry);
out:
	spin_unlock(&mon_lock);

	return result;
}
Ejemplo n.º 2
0
/***********************************************************************
F* Function:     static int register_mon_chain(wdt_mpc8xx_param_t *param,
F*                                             int userproc) P*A*Z*
 *
P* Parameters:   wdt_mpc8xx_param_t *param
P*                - The parameters for the chain to be registered.
P*                  Unused stages should be cleared with 0's.
P*               int userproc
P*                - Flag whether we are called from user or kernel space
P*
P* Returnvalue:  int
P*                - 0  success
P*                  -EINVAL  invalid parameters
P*                  -ENOMEM  out of memory
 *
Z* Intention:    This is the main interface to register a watchdog chain
Z*               either from userspace throught ioctl() or from kernel
Z*               space through the wrapper function
Z*               wdt_mpc8x_register_mon_chain().
Z*               Re-registering an existing chain is explicitely ok, as
Z*               a restarted process has to go through this.  This
Z*               effectively resets the corresponding chain.
Z*               For a detailed description of the parameters, see the
Z*               wdt_mpc8xx(4) manpage.
 *
D* Design:       [email protected]
C* Coding:       [email protected]
V* Verification: [email protected]
 ***********************************************************************/
static int register_mon_chain(wdt_mpc8xx_param_t *param, int userproc)
{
	monitored_chain_t *entry;
	int result=0, i;

	/* Before kmallocing storage we first check the parameters */
	for (i=0; (i<3)&&(param->timer_count[i]); i++)
		if ((param->action[i]<WDT_MPC8XX_ACTION_SIGNAL)||
		    (param->action[i]>WDT_MPC8XX_ACTION_RESET))
			return(-EINVAL);

	debugk("%s: registering WDT8xx monitor\n", __FUNCTION__);

	spin_lock(&mon_lock);

	if ((entry=find_mon_chain_by_chainid(param->chainid))==NULL) {
		/* New chain-id so allocate list entry */
		entry=(monitored_chain_t *)kmalloc(sizeof(monitored_chain_t), GFP_KERNEL);
		if (entry==NULL) {
			result=-ENOMEM;
			goto out;
		}

		/* Copy request data to internal format */
		if (userproc)
			entry->pid=current->pid;
		else
			entry->pid=0;
		entry->chainid=param->chainid;
		entry->signal=param->signal;
		for (i=0; i<2 ; i++) {
			if (entry->action[i]!=0) {
				entry->timer_count[i]=param->timer_count[i];
				entry->action[i]=param->action[i];
			} else {
				/* Fill with stop entries */
				entry->timer_count[i]=2;
				entry->action[i]=WDT_MPC8XX_ACTION_RESET;
			}
		}
					
		/* This is a final stop entry */
		entry->timer_count[3]=2;
		entry->action[3]=WDT_MPC8XX_ACTION_RESET;

		/* Initialize internal data */
		entry->escalation=0;
		entry->expires=jiffies + HZ * entry->timer_count[0];
		insert_mon_chain(entry);
		mon_chains++;
	} else {
		/* Re-registering of active monitor */
		entry->pid=current->pid;
		entry->escalation=0;
		entry->expires=jiffies + HZ * entry->timer_count[0];
		entry->escalation=0;
		list_del(&entry->list);
		insert_mon_chain(entry);
	}

 out:
	spin_unlock(&mon_lock);

	return(result);
}
Ejemplo n.º 3
0
/***********************************************************************
F* Function:     static int process_mon_chains(void) P*A*Z*
 *
P* Parameters:   none
P*
P* Returnvalue:  int
P*                - 0 if the function returns at all
 *
Z* Intention:    This is the core function of the chain functionality.
Z*               The list with the monitored chain is processed and
Z*               expired entries handled appropriately by stepping up
Z*               the escalation ladder.  The escalation actions are
Z*               triggered from here.
 *
D* Design:       [email protected]
C* Coding:       [email protected]
V* Verification: [email protected]
 ***********************************************************************/
static int process_mon_chains(void)
{
	struct list_head *ptr;
	monitored_chain_t *entry;
	int sig;

	spin_lock(&mon_lock);

	for (ptr=mon_list.next; ptr!=&mon_list; ptr=ptr->next) {
		entry=list_entry(ptr, monitored_chain_t, list);
		if (entry->expires<=jiffies) {
			debugk("%s: WDT8xx monitor expired for id %d\n", __FUNCTION__, entry->chainid);
			switch (entry->action[entry->escalation]) {
			case WDT_MPC8XX_ACTION_SIGNAL:
				debugk("WDT_8xx: sending user signal for key %d...\n", entry->chainid);
				sig=(entry->signal)?entry->signal:SIGTERM;
				if (entry->pid)
					kill_proc(entry->pid, sig, 1);
				break;

			case WDT_MPC8XX_ACTION_KILL:
				debugk("WDT_8xx: sending KILL signal for key %d...\n", entry->chainid);
				if (entry->pid)
					kill_proc(entry->pid, SIGKILL, 1);
				break;

			case WDT_MPC8XX_ACTION_REBOOT:
				spin_unlock(&mon_lock);
				wdt_mpc8xx_unregister_mon_chain(entry->chainid);
				printk("WDT_8xx: Rebooting system for key %d...\n", entry->chainid);
				sync();
				sys_reboot(LINUX_REBOOT_MAGIC1,
					   LINUX_REBOOT_MAGIC2,
					   LINUX_REBOOT_CMD_RESTART, NULL);
				break;

			case WDT_MPC8XX_ACTION_RESET:
				printk("WDT_8xx: Resetting system for key %d...\n", entry->chainid);
#ifdef CONFIG_8xx
				m8xx_restart (NULL);
#else
				machine_restart (NULL);
#endif
				break;
				
			default:
				debugk("WDT_8xx: undefined action %d\n", entry->action[entry->escalation]);
				break;
			}
			entry->escalation++;
			entry->expires=jiffies + HZ * 
				entry->timer_count[entry->escalation];
			list_del(&entry->list);
			insert_mon_chain(entry);
		} else
			/* The list is sorted, so we can stop here */
			break;
	}
			
	spin_unlock(&mon_lock);

	return(0);
}
Ejemplo n.º 4
0
/***********************************************************************
F* Function:     static int process_mon_chains(void) P*A*Z*
 *
P* Parameters:   none
P*
P* Returnvalue:  int
P*                - 0 if the function returns at all
 *
Z* Intention:    This is the core function of the chain functionality.
Z*               The list with the monitored chain is processed and
Z*               expired entries handled appropriately by stepping up
Z*               the escalation ladder.  The escalation actions are
Z*               triggered from here.
 *
D* Design:       [email protected]
C* Coding:       [email protected]
V* Verification: [email protected]
 ***********************************************************************/
static int process_mon_chains(void)
{
	struct list_head *ptr;
	monitored_chain_t *entry;
	int sig;

	spin_lock(&mon_lock);

	for (ptr = mon_list.next; ptr != &mon_list; ptr = ptr->next) {
		entry = list_entry(ptr, monitored_chain_t, list);
		if (time_after_eq(jiffies, entry->expires)) {
			debugk("%s: WD monitor expired for id %d\n",
				__FUNCTION__, entry->chainid);
			switch (entry->action[entry->escalation]) {
			case WD_ACTION_SIGNAL:
				debugk("WD: sending user signal for key "
					"%d...\n", entry->chainid);
				sig = (entry->signal) ? entry->signal : SIGTERM;
				if (entry->pid)
					kill_proc_info(sig, SEND_SIG_PRIV, entry->pid);
				break;
			case WD_ACTION_KILL:
				debugk("WD: sending KILL signal for key "
					"%d...\n", entry->chainid);
				if (entry->pid)
					kill_proc_info(SIGKILL, SEND_SIG_PRIV, entry->pid);
				break;
			case WD_ACTION_REBOOT:
				spin_unlock(&mon_lock);
				wd_unregister_mon_chain(entry->chainid);
				printk("WD: Rebooting system for key "
					"%d...\n", entry->chainid);
				flush_cache_all();
				/*
				 * XXX This is not safe to call in interrupt
				 * context.
				 */
				sys_reboot(LINUX_REBOOT_MAGIC1,
					LINUX_REBOOT_MAGIC2,
					LINUX_REBOOT_CMD_RESTART,
					NULL);
				break;
			case WD_ACTION_RESET:
				printk("WD: Resetting system for key "
					"%d...\n", entry->chainid);
				BUG_ON(wd_hw_functions.wd_machine_restart
					== NULL);
				wd_hw_functions.wd_machine_restart();
				break;

			default:
				debugk("WD: undefined action %d\n",
					entry->action[entry->escalation]);
				break;
			}
			entry->escalation++;
			entry->expires = jiffies + HZ * 
				entry->timer_count[entry->escalation];
			list_del(&entry->list);
			insert_mon_chain(entry);
		} else
			/* The list is sorted, so we can stop here */
			break;
	}

	spin_unlock(&mon_lock);

	return 0;
}