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