Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2016, Citrix Systems, Inc.
3 : : *
4 : : * All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions are met:
8 : : *
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : * 2. Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : * 3. Neither the name of the copyright holder nor the names of its
15 : : * contributors may be used to endorse or promote products derived from
16 : : * this software without specific prior written permission.
17 : : *
18 : : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 : : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 : : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 : : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22 : : * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 : : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 : : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 : : * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 : : * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 : : * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 : : * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 : : */
30 : :
31 : : #ifdef HAVE_CONFIG_H
32 : : #include "config.h"
33 : : #endif
34 : :
35 : : #include <stdio.h>
36 : : #include <errno.h>
37 : : #include <unistd.h>
38 : : #include <stdlib.h>
39 : : #include <string.h>
40 : : #include <signal.h>
41 : : #include <sys/wait.h>
42 : :
43 : : #include "tap-ctl.h"
44 : : #include "blktap.h"
45 : :
46 : : static pid_t
47 : 0 : __tap_ctl_spawn(int *readfd)
48 : : {
49 : : int child, channel[2];
50 : :
51 [ # # ]: 0 : if (pipe(channel)) {
52 : 0 : EPRINTF("pipe failed: %d\n", errno);
53 : 0 : return -errno;
54 : : }
55 : :
56 [ # # ]: 0 : if ((child = fork()) == -1) {
57 : 0 : EPRINTF("fork failed: %d\n", errno);
58 : 0 : return -errno;
59 : : }
60 : :
61 [ # # ]: 0 : if (child) {
62 : 0 : close(channel[1]);
63 : 0 : *readfd = channel[0];
64 : 0 : return child;
65 : : }
66 : :
67 [ # # ]: 0 : if (dup2(channel[1], STDOUT_FILENO) == -1) {
68 : 0 : EPRINTF("dup2 failed: %d\n", errno);
69 : 0 : exit(errno);
70 : : }
71 : :
72 [ # # ]: 0 : if (dup2(channel[1], STDERR_FILENO) == -1) {
73 : 0 : EPRINTF("dup2 failed: %d\n", errno);
74 : 0 : exit(errno);
75 : : }
76 : :
77 : 0 : close(channel[0]);
78 : 0 : close(channel[1]);
79 : :
80 : 0 : execl(TAPDISK_EXECDIR "/" TAPDISK_EXEC, TAPDISK_EXEC,
81 : : NULL);
82 : :
83 : 0 : exit(errno);
84 : : }
85 : :
86 : : pid_t
87 : 3 : tap_ctl_get_pid(const int id)
88 : : {
89 : : int err;
90 : : tapdisk_message_t message;
91 : :
92 : : memset(&message, 0, sizeof(message));
93 : 3 : message.type = TAPDISK_MESSAGE_PID;
94 : :
95 : 3 : err = tap_ctl_connect_send_and_receive(id, &message, NULL);
96 [ + - ]: 3 : if (err)
97 : 3 : return err;
98 : :
99 : 3 : return message.u.tapdisk_pid;
100 : : }
101 : :
102 : : static int
103 : 0 : tap_ctl_wait(pid_t child)
104 : : {
105 : : pid_t pid;
106 : : int status;
107 : :
108 : 0 : pid = waitpid(child, &status, 0);
109 [ # # ]: 0 : if (pid < 0) {
110 : 0 : EPRINTF("wait(%d) failed, err %d\n", child, errno);
111 : 0 : return -errno;
112 : : }
113 : :
114 [ # # ]: 0 : if (WIFEXITED(status)) {
115 : 0 : int code = WEXITSTATUS(status);
116 [ # # ]: 0 : if (code)
117 : : EPRINTF("tapdisk2[%d] failed, status %d\n", child, code);
118 : 0 : return -code;
119 : : }
120 : :
121 [ # # ]: 0 : if (WIFSIGNALED(status)) {
122 : 0 : int signo = WTERMSIG(status);
123 : : EPRINTF("tapdisk2[%d] killed by signal %d\n", child, signo);
124 [ # # ]: 0 : if (signo == SIGUSR1)
125 : : /* NB. there's a race between tapdisk's
126 : : * sigaction init and xen-bugtool shooting
127 : : * debug signals. If killed by something as
128 : : * innocuous as USR1, then retry. */
129 : : return -EAGAIN;
130 : 0 : return -EINTR;
131 : : }
132 : :
133 : 0 : EPRINTF("tapdisk2[%d]: unexpected status %#x\n", child, status);
134 : : return -EAGAIN;
135 : : }
136 : :
137 : : static int
138 : 0 : tap_ctl_get_child_id(int readfd)
139 : : {
140 : : int id;
141 : : FILE *f;
142 : :
143 : 0 : f = fdopen(readfd, "r");
144 [ # # ]: 0 : if (!f) {
145 : 0 : EPRINTF("fdopen failed: %d\n", errno);
146 : 0 : return -1;
147 : : }
148 : :
149 : 0 : errno = 0;
150 [ # # ]: 0 : if (fscanf(f, BLKTAP2_CONTROL_DIR"/"
151 : : BLKTAP2_CONTROL_SOCKET"%d", &id) != 1) {
152 [ # # ]: 0 : errno = (errno ? : EINVAL);
153 : 0 : EPRINTF("parsing id failed: %d\n", errno);
154 : 0 : id = -1;
155 : : }
156 : :
157 : 0 : fclose(f);
158 : 0 : return id;
159 : : }
160 : :
161 : : int
162 : 0 : tap_ctl_spawn(void)
163 : : {
164 : : pid_t child;
165 : : int err, id, readfd;
166 : :
167 : 0 : readfd = -1;
168 : :
169 : : again:
170 : 0 : child = __tap_ctl_spawn(&readfd);
171 [ # # ]: 0 : if (child < 0)
172 : 0 : return child;
173 : :
174 : 0 : err = tap_ctl_wait(child);
175 [ # # ]: 0 : if (err) {
176 [ # # ]: 0 : if (err == -EAGAIN)
177 : : goto again;
178 : : return err;
179 : : }
180 : :
181 : 0 : id = tap_ctl_get_child_id(readfd);
182 [ # # ]: 0 : if (id < 0) {
183 : 0 : EPRINTF("get_id failed, child %d err %d\n", child, errno);
184 : : return id;
185 : : }
186 : :
187 : : return id;
188 : : }
|