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

📄 ipmi_watchdog.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 2 页
字号:
static ssize_t ipmi_write(struct file *file,			  const char  *buf,			  size_t      len,			  loff_t      *ppos){	int rv;	/*  Can't seek (pwrite) on this device  */	if (ppos != &file->f_pos)		return -ESPIPE;	if (len) {		rv = ipmi_heartbeat();		if (rv)			return rv;		return 1;	}	return 0;}static ssize_t ipmi_read(struct file *file,			 char        *buf,			 size_t      count,			 loff_t      *ppos){	int          rv = 0;	wait_queue_t wait;	/*  Can't seek (pread) on this device  */	if (ppos != &file->f_pos)		return -ESPIPE;	if (count <= 0)		return 0;	/* Reading returns if the pretimeout has gone off, and it only does	   it once per pretimeout. */	spin_lock(&ipmi_read_lock);	if (!data_to_read) {		if (file->f_flags & O_NONBLOCK) {			rv = -EAGAIN;			goto out;		}				init_waitqueue_entry(&wait, current);		add_wait_queue(&read_q, &wait);		while (!data_to_read) {			set_current_state(TASK_INTERRUPTIBLE);			spin_unlock(&ipmi_read_lock);			schedule();			spin_lock(&ipmi_read_lock);		}		remove_wait_queue(&read_q, &wait);	    		if (signal_pending(current)) {			rv = -ERESTARTSYS;			goto out;		}	}	data_to_read = 0; out:	spin_unlock(&ipmi_read_lock);	if (rv == 0) {		if (copy_to_user(buf, &data_to_read, 1))			rv = -EFAULT;		else			rv = 1;	}	return rv;}static int ipmi_open(struct inode *ino, struct file *filep){        switch (minor(ino->i_rdev))        {                case WATCHDOG_MINOR:                    if (ipmi_wdog_open)                        return -EBUSY;                    ipmi_wdog_open = 1;		    /* Don't start the timer now, let it start on the		       first heartbeat. */		    ipmi_start_timer_on_heartbeat = 1;                    return(0);                default:                    return (-ENODEV);        }}static unsigned int ipmi_poll(struct file *file, poll_table *wait){	unsigned int mask = 0;		poll_wait(file, &read_q, wait);	spin_lock(&ipmi_read_lock);	if (data_to_read)		mask |= (POLLIN | POLLRDNORM);	spin_unlock(&ipmi_read_lock);	return mask;}static int ipmi_fasync(int fd, struct file *file, int on){	int result;	result = fasync_helper(fd, file, on, &fasync_q);	return (result);}static int ipmi_close(struct inode *ino, struct file *filep){	if (minor(ino->i_rdev)==WATCHDOG_MINOR)	{#ifndef CONFIG_WATCHDOG_NOWAYOUT			ipmi_watchdog_state = WDOG_TIMEOUT_NONE;		ipmi_set_timeout();#endif			        ipmi_wdog_open = 0;	}	ipmi_fasync (-1, filep, 0);	return 0;}static struct file_operations ipmi_wdog_fops = {	.owner   = THIS_MODULE,	.read    = ipmi_read,	.poll    = ipmi_poll,	.write   = ipmi_write,	.ioctl   = ipmi_ioctl,	.open    = ipmi_open,	.release = ipmi_close,	.fasync  = ipmi_fasync,};static struct miscdevice ipmi_wdog_miscdev = {	WATCHDOG_MINOR,	"watchdog",	&ipmi_wdog_fops};static DECLARE_RWSEM(register_sem);static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,				  void                 *handler_data){	if (msg->msg.data[0] != 0) {		printk(KERN_ERR "IPMI Watchdog response: Error %x on cmd %x\n",		       msg->msg.data[0],		       msg->msg.cmd);	}		ipmi_free_recv_msg(msg);}static void ipmi_wdog_pretimeout_handler(void *handler_data){	if (preaction_val != WDOG_PRETIMEOUT_NONE) {		if (preop_val == WDOG_PREOP_PANIC)			panic("Watchdog pre-timeout");		else if (preop_val == WDOG_PREOP_GIVE_DATA) {			spin_lock(&ipmi_read_lock);			data_to_read = 1;			wake_up_interruptible(&read_q);			kill_fasync(&fasync_q, SIGIO, POLL_IN);			/* On some machines, the heartbeat will give			   an error and not work unless we re-enable			   the timer.   So do so. */			pretimeout_since_last_heartbeat = 1;			spin_unlock(&ipmi_read_lock);		}	}}static struct ipmi_user_hndl ipmi_hndlrs ={	.ipmi_recv_hndl           = ipmi_wdog_msg_handler,	.ipmi_watchdog_pretimeout = ipmi_wdog_pretimeout_handler};static void ipmi_register_watchdog(int ipmi_intf){	int rv = -EBUSY;	down_read(&register_sem);	if (watchdog_user)		goto out;	rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user);	if (rv < 0) {		printk("IPMI watchdog: Unable to register with ipmi\n");		goto out;	}	ipmi_get_version(watchdog_user,			 &ipmi_version_major,			 &ipmi_version_minor);	rv = misc_register(&ipmi_wdog_miscdev);	if (rv < 0) {		ipmi_destroy_user(watchdog_user);		watchdog_user = NULL;		printk("IPMI watchdog: Unable to register misc device\n");	} out:	up_write(&register_sem);	if ((start_now) && (rv == 0)) {		/* Run from startup, so start the timer now. */		start_now = 0; /* Disable this function after first startup. */		ipmi_watchdog_state = action_val;		ipmi_set_timeout();		printk("Starting IPMI Watchdog now!\n");	}}#ifdef HAVE_NMI_HANDLERstatic intipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled){	/* If no one else handled the NMI, we assume it was the IPMI           watchdog. */	if ((!handled) && (preop_val == WDOG_PREOP_PANIC))		panic("IPMI watchdog pre-timeout");	return NOTIFY_DONE;}static struct nmi_handler ipmi_nmi_handler ={	.dev_name = "ipmi_watchdog",	.dev_id   = NULL,	.handler  = ipmi_nmi,	.priority = 0, /* Call us last. */};#endifstatic int wdog_reboot_handler(struct notifier_block *this,			       unsigned long         code,			       void                  *unused){	static int reboot_event_handled = 0;	if ((watchdog_user) && (!reboot_event_handled)) {		/* Make sure we only do this once. */		reboot_event_handled = 1;		if (code == SYS_DOWN || code == SYS_HALT) {			/* Disable the WDT if we are shutting down. */			ipmi_watchdog_state = WDOG_TIMEOUT_NONE;			panic_halt_ipmi_set_timeout();		} else {			/* Set a long timer to let the reboot happens, but			   reboot if it hangs. */			timeout = 120;			pretimeout = 0;			ipmi_watchdog_state = WDOG_TIMEOUT_RESET;			panic_halt_ipmi_set_timeout();		}	}	return NOTIFY_OK;}static struct notifier_block wdog_reboot_notifier = {	wdog_reboot_handler,	NULL,	0};extern int panic_timeout; /* Why isn't this defined anywhere? */static int wdog_panic_handler(struct notifier_block *this,			      unsigned long         event,			      void                  *unused){	static int panic_event_handled = 0;	/* On a panic, if we have a panic timeout, make sure that the thing	   reboots, even if it hangs during that panic. */	if (watchdog_user && !panic_event_handled && (panic_timeout > 0)) {		/* Make sure the panic doesn't hang, and make sure we		   do this only once. */		panic_event_handled = 1;	    		timeout = panic_timeout + 120;		if (timeout > 255)			timeout = 255;		pretimeout = 0;		ipmi_watchdog_state = WDOG_TIMEOUT_RESET;		panic_halt_ipmi_set_timeout();	}	return NOTIFY_OK;}static struct notifier_block wdog_panic_notifier = {	wdog_panic_handler,	NULL,	150   /* priority: INT_MAX >= x >= 0 */};static void ipmi_new_smi(int if_num){	ipmi_register_watchdog(if_num);}static void ipmi_smi_gone(int if_num){	/* This can never be called, because once the watchdog is	   registered, the interface can't go away until the watchdog	   is unregistered. */}static struct ipmi_smi_watcher smi_watcher ={	.new_smi  = ipmi_new_smi,	.smi_gone = ipmi_smi_gone};static int __init ipmi_wdog_init(void){	int rv;	if (strcmp(action, "reset") == 0) {		action_val = WDOG_TIMEOUT_RESET;	} else if (strcmp(action, "none") == 0) {		action_val = WDOG_TIMEOUT_NONE;	} else if (strcmp(action, "power_cycle") == 0) {		action_val = WDOG_TIMEOUT_POWER_CYCLE;	} else if (strcmp(action, "power_off") == 0) {		action_val = WDOG_TIMEOUT_POWER_DOWN;	} else {		action_val = WDOG_TIMEOUT_RESET;		printk("ipmi_watchdog: Unknown action '%s', defaulting to"		       " reset\n", action);	}	if (strcmp(preaction, "pre_none") == 0) {		preaction_val = WDOG_PRETIMEOUT_NONE;	} else if (strcmp(preaction, "pre_smi") == 0) {		preaction_val = WDOG_PRETIMEOUT_SMI;#ifdef HAVE_NMI_HANDLER	} else if (strcmp(preaction, "pre_nmi") == 0) {		preaction_val = WDOG_PRETIMEOUT_NMI;#endif	} else if (strcmp(preaction, "pre_int") == 0) {		preaction_val = WDOG_PRETIMEOUT_MSG_INT;	} else {		action_val = WDOG_PRETIMEOUT_NONE;		printk("ipmi_watchdog: Unknown preaction '%s', defaulting to"		       " none\n", preaction);	}	if (strcmp(preop, "preop_none") == 0) {		preop_val = WDOG_PREOP_NONE;	} else if (strcmp(preop, "preop_panic") == 0) {		preop_val = WDOG_PREOP_PANIC;	} else if (strcmp(preop, "preop_give_data") == 0) {		preop_val = WDOG_PREOP_GIVE_DATA;	} else {		action_val = WDOG_PREOP_NONE;		printk("ipmi_watchdog: Unknown preop '%s', defaulting to"		       " none\n", preop);	}#ifdef HAVE_NMI_HANDLER	if (preaction_val == WDOG_PRETIMEOUT_NMI) {		if (preop_val == WDOG_PREOP_GIVE_DATA) {			printk(KERN_WARNING			       "ipmi_watchdog: Pretimeout op is to give data"			       " but NMI pretimeout is enabled, setting"			       " pretimeout op to none\n");			preop_val = WDOG_PREOP_NONE;		}#ifdef CONFIG_X86_LOCAL_APIC		if (nmi_watchdog == NMI_IO_APIC) {			printk(KERN_WARNING			       "ipmi_watchdog: nmi_watchdog is set to IO APIC"			       " mode (value is %d), that is incompatible"			       " with using NMI in the IPMI watchdog."			       " Disabling IPMI nmi pretimeout.\n",			       nmi_watchdog);			preaction_val = WDOG_PRETIMEOUT_NONE;		} else {#endif		rv = request_nmi(&ipmi_nmi_handler);		if (rv) {			printk(KERN_WARNING			       "ipmi_watchdog: Can't register nmi handler\n");			return rv;		}#ifdef CONFIG_X86_LOCAL_APIC		}#endif	}#endif	rv = ipmi_smi_watcher_register(&smi_watcher);	if (rv) {#ifdef HAVE_NMI_HANDLER		if (preaction_val == WDOG_PRETIMEOUT_NMI)			release_nmi(&ipmi_nmi_handler);#endif		printk(KERN_WARNING		       "ipmi_watchdog: can't register smi watcher\n");		return rv;	}	register_reboot_notifier(&wdog_reboot_notifier);	notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);	printk(KERN_INFO "IPMI watchdog by "	       "Corey Minyard (minyard@mvista.com)\n");	return 0;}#ifdef MODULEstatic void ipmi_unregister_watchdog(void){	int rv;	down_write(&register_sem);#ifdef HAVE_NMI_HANDLER	if (preaction_val == WDOG_PRETIMEOUT_NMI)		release_nmi(&ipmi_nmi_handler);#endif	notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier);	unregister_reboot_notifier(&wdog_reboot_notifier);	if (! watchdog_user)		goto out;	/* Make sure no one can call us any more. */	misc_deregister(&ipmi_wdog_miscdev);	/*  Disable the timer. */	ipmi_watchdog_state = WDOG_TIMEOUT_NONE;	ipmi_set_timeout();	/* Wait to make sure the message makes it out.  The lower layer has	   pointers to our buffers, we want to make sure they are done before	   we release our memory. */	while (atomic_read(&set_timeout_tofree)) {		schedule_timeout(1);	}	/* Disconnect from IPMI. */	rv = ipmi_destroy_user(watchdog_user);	if (rv) {		printk(KERN_WARNING		       "IPMI Watchdog, error unlinking from IPMI: %d\n",		       rv);	}	watchdog_user = NULL; out:	up_write(&register_sem);}static void __exit ipmi_wdog_exit(void){	ipmi_smi_watcher_unregister(&smi_watcher);	ipmi_unregister_watchdog();}module_exit(ipmi_wdog_exit);#elsestatic int __init ipmi_wdog_setup(char *str){	int  val;	int  rv;	char *option;	rv = get_option(&str, &val);	if (rv == 0)		return 1;	if (val > 0)		timeout = val;	if (rv == 1)		return 1;	rv = get_option(&str, &val);	if (rv == 0)		return 1;	if (val >= 0)		pretimeout = val;	if (rv == 1)		return 1;	while ((option = strsep(&str, ",")) != NULL) {		if (strcmp(option, "reset") == 0) {			action = "reset";		}		else if (strcmp(option, "none") == 0) {			action = "none";		}		else if (strcmp(option, "power_cycle") == 0) {			action = "power_cycle";		}		else if (strcmp(option, "power_off") == 0) {			action = "power_off";		}		else if (strcmp(option, "pre_none") == 0) {			preaction = "pre_none";		}		else if (strcmp(option, "pre_smi") == 0) {			preaction = "pre_smi";		}#ifdef HAVE_NMI_HANDLER		else if (strcmp(option, "pre_nmi") == 0) {			preaction = "pre_nmi";		}#endif		else if (strcmp(option, "pre_int") == 0) {			preaction = "pre_int";		}		else if (strcmp(option, "start_now") == 0) {			start_now = 1;		}		else if (strcmp(option, "preop_none") == 0) {			preop = "preop_none";		}		else if (strcmp(option, "preop_panic") == 0) {			preop = "preop_panic";		}		else if (strcmp(option, "preop_none") == 0) {			preop = "preop_give_data";		} else {		    printk("Unknown IPMI watchdog option: '%s'\n", option);		}	}	return 1;}__setup("ipmi_wdog=", ipmi_wdog_setup);#endifEXPORT_SYMBOL_GPL(ipmi_delayed_shutdown);module_init(ipmi_wdog_init);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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