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