| 
									
										
										
										
											2007-02-10 01:43:58 -08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  |  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * Licensed under the GPL | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							| 
									
										
										
										
											2012-10-08 03:27:32 +01:00
										 |  |  | #include <os.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | struct dog_data { | 
					
						
							|  |  |  | 	int stdin; | 
					
						
							|  |  |  | 	int stdout; | 
					
						
							|  |  |  | 	int close_me[2]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void pre_exec(void *d) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct dog_data *data = d; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dup2(data->stdin, 0); | 
					
						
							|  |  |  | 	dup2(data->stdout, 1); | 
					
						
							|  |  |  | 	dup2(data->stdout, 2); | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  | 	close(data->stdin); | 
					
						
							|  |  |  | 	close(data->stdout); | 
					
						
							|  |  |  | 	close(data->close_me[0]); | 
					
						
							|  |  |  | 	close(data->close_me[1]); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct dog_data data; | 
					
						
							|  |  |  | 	int in_fds[2], out_fds[2], pid, n, err; | 
					
						
							| 
									
										
										
										
											2011-07-25 17:12:55 -07:00
										 |  |  | 	char pid_buf[sizeof("nnnnnnn\0")], c; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; | 
					
						
							| 
									
										
										
										
											2007-02-10 01:43:58 -08:00
										 |  |  | 	char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				  NULL }; | 
					
						
							|  |  |  | 	char **args = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = os_pipe(in_fds, 1, 0); | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  | 	if (err < 0) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		printk("harddog_open - os_pipe failed, err = %d\n", -err); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = os_pipe(out_fds, 1, 0); | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  | 	if (err < 0) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		printk("harddog_open - os_pipe failed, err = %d\n", -err); | 
					
						
							|  |  |  | 		goto out_close_in; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data.stdin = out_fds[0]; | 
					
						
							|  |  |  | 	data.stdout = in_fds[1]; | 
					
						
							|  |  |  | 	data.close_me[0] = out_fds[1]; | 
					
						
							|  |  |  | 	data.close_me[1] = in_fds[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  | 	if (sock != NULL) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		mconsole_args[2] = sock; | 
					
						
							|  |  |  | 		args = mconsole_args; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		/* XXX The os_getpid() is not SMP correct */ | 
					
						
							| 
									
										
										
										
											2007-10-16 01:26:56 -07:00
										 |  |  | 		sprintf(pid_buf, "%d", os_getpid()); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		args = pid_args; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-15 23:38:56 -07:00
										 |  |  | 	pid = run_helper(pre_exec, &data, args); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  | 	close(out_fds[0]); | 
					
						
							|  |  |  | 	close(in_fds[1]); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  | 	if (pid < 0) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		err = -pid; | 
					
						
							|  |  |  | 		printk("harddog_open - run_helper failed, errno = %d\n", -err); | 
					
						
							|  |  |  | 		goto out_close_out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  | 	n = read(in_fds[0], &c, sizeof(c)); | 
					
						
							|  |  |  | 	if (n == 0) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		printk("harddog_open - EOF on watchdog pipe\n"); | 
					
						
							| 
									
										
										
										
											2008-02-23 15:23:49 -08:00
										 |  |  | 		helper_wait(pid); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		err = -EIO; | 
					
						
							|  |  |  | 		goto out_close_out; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  | 	else if (n < 0) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		printk("harddog_open - read of watchdog pipe failed, " | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  | 		       "err = %d\n", errno); | 
					
						
							| 
									
										
										
										
											2008-02-23 15:23:49 -08:00
										 |  |  | 		helper_wait(pid); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		err = n; | 
					
						
							|  |  |  | 		goto out_close_out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	*in_fd_ret = in_fds[0]; | 
					
						
							|  |  |  | 	*out_fd_ret = out_fds[1]; | 
					
						
							| 
									
										
										
										
											2007-02-10 01:43:58 -08:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |  out_close_in: | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  | 	close(in_fds[0]); | 
					
						
							|  |  |  | 	close(in_fds[1]); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  out_close_out: | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  | 	close(out_fds[0]); | 
					
						
							|  |  |  | 	close(out_fds[1]); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  out: | 
					
						
							| 
									
										
										
										
											2007-02-10 01:43:58 -08:00
										 |  |  | 	return err; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void stop_watchdog(int in_fd, int out_fd) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  | 	close(in_fd); | 
					
						
							|  |  |  | 	close(out_fd); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ping_watchdog(int fd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 	char c = '\n'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-16 01:27:08 -07:00
										 |  |  | 	n = write(fd, &c, sizeof(c)); | 
					
						
							|  |  |  | 	if (n != sizeof(c)) { | 
					
						
							|  |  |  | 		printk("ping_watchdog - write failed, ret = %d, err = %d\n", | 
					
						
							|  |  |  | 		       n, errno); | 
					
						
							|  |  |  | 		if (n < 0) | 
					
						
							| 
									
										
										
										
											2007-02-10 01:43:58 -08:00
										 |  |  | 			return n; | 
					
						
							|  |  |  | 		return -EIO; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |