| Jeff Dike | 5bbcbec | 2007-02-10 01:43:58 -0800 | [diff] [blame] | 1 | /* | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3 | * Licensed under the GPL | 
|  | 4 | */ | 
|  | 5 |  | 
|  | 6 | #include <stdio.h> | 
|  | 7 | #include <unistd.h> | 
|  | 8 | #include <errno.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 9 | #include "os.h" | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 10 | #include "user.h" | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11 |  | 
|  | 12 | struct dog_data { | 
|  | 13 | int stdin; | 
|  | 14 | int stdout; | 
|  | 15 | int close_me[2]; | 
|  | 16 | }; | 
|  | 17 |  | 
|  | 18 | static void pre_exec(void *d) | 
|  | 19 | { | 
|  | 20 | struct dog_data *data = d; | 
|  | 21 |  | 
|  | 22 | dup2(data->stdin, 0); | 
|  | 23 | dup2(data->stdout, 1); | 
|  | 24 | dup2(data->stdout, 2); | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 25 | close(data->stdin); | 
|  | 26 | close(data->stdout); | 
|  | 27 | close(data->close_me[0]); | 
|  | 28 | close(data->close_me[1]); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 29 | } | 
|  | 30 |  | 
|  | 31 | int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) | 
|  | 32 | { | 
|  | 33 | struct dog_data data; | 
|  | 34 | int in_fds[2], out_fds[2], pid, n, err; | 
|  | 35 | char pid_buf[sizeof("nnnnn\0")], c; | 
|  | 36 | char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; | 
| Jeff Dike | 5bbcbec | 2007-02-10 01:43:58 -0800 | [diff] [blame] | 37 | char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 38 | NULL }; | 
|  | 39 | char **args = NULL; | 
|  | 40 |  | 
|  | 41 | err = os_pipe(in_fds, 1, 0); | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 42 | if (err < 0) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 43 | printk("harddog_open - os_pipe failed, err = %d\n", -err); | 
|  | 44 | goto out; | 
|  | 45 | } | 
|  | 46 |  | 
|  | 47 | err = os_pipe(out_fds, 1, 0); | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 48 | if (err < 0) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 49 | printk("harddog_open - os_pipe failed, err = %d\n", -err); | 
|  | 50 | goto out_close_in; | 
|  | 51 | } | 
|  | 52 |  | 
|  | 53 | data.stdin = out_fds[0]; | 
|  | 54 | data.stdout = in_fds[1]; | 
|  | 55 | data.close_me[0] = out_fds[1]; | 
|  | 56 | data.close_me[1] = in_fds[0]; | 
|  | 57 |  | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 58 | if (sock != NULL) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 59 | mconsole_args[2] = sock; | 
|  | 60 | args = mconsole_args; | 
|  | 61 | } | 
|  | 62 | else { | 
|  | 63 | /* XXX The os_getpid() is not SMP correct */ | 
| Jeff Dike | 6aa802c | 2007-10-16 01:26:56 -0700 | [diff] [blame] | 64 | sprintf(pid_buf, "%d", os_getpid()); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 65 | args = pid_args; | 
|  | 66 | } | 
|  | 67 |  | 
| Jeff Dike | c439901 | 2007-07-15 23:38:56 -0700 | [diff] [blame] | 68 | pid = run_helper(pre_exec, &data, args); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 69 |  | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 70 | close(out_fds[0]); | 
|  | 71 | close(in_fds[1]); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 72 |  | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 73 | if (pid < 0) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 74 | err = -pid; | 
|  | 75 | printk("harddog_open - run_helper failed, errno = %d\n", -err); | 
|  | 76 | goto out_close_out; | 
|  | 77 | } | 
|  | 78 |  | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 79 | n = read(in_fds[0], &c, sizeof(c)); | 
|  | 80 | if (n == 0) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 81 | printk("harddog_open - EOF on watchdog pipe\n"); | 
| Johann Felix Soden | e4d06b3 | 2008-02-23 15:23:49 -0800 | [diff] [blame] | 82 | helper_wait(pid); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 83 | err = -EIO; | 
|  | 84 | goto out_close_out; | 
|  | 85 | } | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 86 | else if (n < 0) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 87 | printk("harddog_open - read of watchdog pipe failed, " | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 88 | "err = %d\n", errno); | 
| Johann Felix Soden | e4d06b3 | 2008-02-23 15:23:49 -0800 | [diff] [blame] | 89 | helper_wait(pid); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 90 | err = n; | 
|  | 91 | goto out_close_out; | 
|  | 92 | } | 
|  | 93 | *in_fd_ret = in_fds[0]; | 
|  | 94 | *out_fd_ret = out_fds[1]; | 
| Jeff Dike | 5bbcbec | 2007-02-10 01:43:58 -0800 | [diff] [blame] | 95 | return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 96 |  | 
|  | 97 | out_close_in: | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 98 | close(in_fds[0]); | 
|  | 99 | close(in_fds[1]); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 100 | out_close_out: | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 101 | close(out_fds[0]); | 
|  | 102 | close(out_fds[1]); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 103 | out: | 
| Jeff Dike | 5bbcbec | 2007-02-10 01:43:58 -0800 | [diff] [blame] | 104 | return err; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 105 | } | 
|  | 106 |  | 
|  | 107 | void stop_watchdog(int in_fd, int out_fd) | 
|  | 108 | { | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 109 | close(in_fd); | 
|  | 110 | close(out_fd); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 111 | } | 
|  | 112 |  | 
|  | 113 | int ping_watchdog(int fd) | 
|  | 114 | { | 
|  | 115 | int n; | 
|  | 116 | char c = '\n'; | 
|  | 117 |  | 
| Jeff Dike | 8ca842c | 2007-10-16 01:27:08 -0700 | [diff] [blame] | 118 | n = write(fd, &c, sizeof(c)); | 
|  | 119 | if (n != sizeof(c)) { | 
|  | 120 | printk("ping_watchdog - write failed, ret = %d, err = %d\n", | 
|  | 121 | n, errno); | 
|  | 122 | if (n < 0) | 
| Jeff Dike | 5bbcbec | 2007-02-10 01:43:58 -0800 | [diff] [blame] | 123 | return n; | 
|  | 124 | return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 125 | } | 
|  | 126 | return 1; | 
|  | 127 |  | 
|  | 128 | } |