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