debuggers.hg

view tools/blktap2/drivers/tapdisk-ipc.c @ 20915:07f33d124053

blktap2: Sort out tapdisk IPC init.

Move I/O and event callbacks setup out of tapdisk-server, into
tapdisk-ipc.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jan 29 08:53:52 2010 +0000 (2010-01-29)
parents 1c627434605e
children
line source
1 /*
2 * Copyright (c) 2008, XenSource Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of XenSource Inc. nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
20 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 #include <stdio.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <fcntl.h>
35 #include "tapdisk.h"
36 #include "tapdisk-ipc.h"
37 #include "tapdisk-vbd.h"
38 #include "tapdisk-server.h"
40 static void
41 tapdisk_ipc_read_event(event_id_t id, char mode, void *private)
42 {
43 td_ipc_t *ipc = private;
44 tapdisk_ipc_read(ipc);
45 }
47 static void
48 __tapdisk_ipc_init(td_ipc_t *ipc)
49 {
50 ipc->rfd = -1;
51 ipc->wfd = -1;
52 ipc->rfd_event = -1;
53 }
55 int
56 tapdisk_ipc_open(td_ipc_t *ipc, const char *read, const char *write)
57 {
58 int err;
60 memset(ipc, 0, sizeof(td_ipc_t));
61 __tapdisk_ipc_init(ipc);
63 if (read) {
64 ipc->rfd = open(read, O_RDWR | O_NONBLOCK);
65 if (ipc->rfd < 0) {
66 err = -errno;
67 EPRINTF("FD open failed %s: %d\n", read, err);
68 goto fail;
69 }
71 ipc->rfd_event =
72 tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
73 ipc->rfd, 0,
74 tapdisk_ipc_read_event,
75 ipc);
76 if (ipc->rfd_event < 0) {
77 err = ipc->rfd_event;
78 goto fail;
79 }
80 }
82 if (write) {
83 ipc->wfd = open(write, O_RDWR | O_NONBLOCK);
84 if (ipc->wfd < 0) {
85 err = -errno;
86 EPRINTF("FD open failed %s, %d\n", write, err);
87 goto fail;
88 }
89 }
91 return 0;
93 fail:
94 tapdisk_ipc_close(ipc);
95 return err;
96 }
98 void
99 tapdisk_ipc_close(td_ipc_t *ipc)
100 {
101 if (ipc->rfd > 0)
102 close(ipc->rfd);
104 if (ipc->wfd > 0)
105 close(ipc->wfd);
107 if (ipc->rfd_event >= 0)
108 tapdisk_server_unregister_event(ipc->rfd_event);
110 __tapdisk_ipc_init(ipc);
111 }
113 static int
114 tapdisk_ipc_write_message(int fd, tapdisk_message_t *message, int timeout)
115 {
116 fd_set writefds;
117 int ret, len, offset;
118 struct timeval tv, *t;
120 t = NULL;
121 offset = 0;
122 len = sizeof(tapdisk_message_t);
124 if (timeout) {
125 tv.tv_sec = timeout;
126 tv.tv_usec = 0;
127 t = &tv;
128 }
130 DPRINTF("sending '%s' message (uuid = %u)\n",
131 tapdisk_message_name(message->type), message->cookie);
133 while (offset < len) {
134 FD_ZERO(&writefds);
135 FD_SET(fd, &writefds);
137 /* we don't bother reinitializing tv. at worst, it will wait a
138 * bit more time than expected. */
140 ret = select(fd + 1, NULL, &writefds, NULL, t);
141 if (ret == -1)
142 break;
143 else if (FD_ISSET(fd, &writefds)) {
144 ret = write(fd, message + offset, len - offset);
145 if (ret <= 0)
146 break;
147 offset += ret;
148 } else
149 break;
150 }
152 if (offset != len) {
153 EPRINTF("failure writing message\n");
154 return -EIO;
155 }
157 return 0;
158 }
160 int
161 tapdisk_ipc_write(td_ipc_t *ipc, int type)
162 {
163 tapdisk_message_t message;
165 if (ipc->wfd == -1)
166 return 0;
168 memset(&message, 0, sizeof(tapdisk_message_t));
169 message.type = type;
170 message.cookie = ipc->uuid;
172 return tapdisk_ipc_write_message(ipc->wfd, &message, 2);
173 }
175 int
176 tapdisk_ipc_write_error(td_ipc_t *ipc, const char *text)
177 {
178 tapdisk_message_t message;
180 memset(&message, 0, sizeof(message));
181 message.type = TAPDISK_MESSAGE_RUNTIME_ERROR;
182 message.cookie = ipc->uuid;
183 snprintf(message.u.string.text, sizeof(message.u.string.text), "%s", text);
185 return tapdisk_ipc_write_message(ipc->wfd, &message, 2);
186 }
188 static int
189 tapdisk_ipc_read_message(int fd, tapdisk_message_t *message, int timeout)
190 {
191 fd_set readfds;
192 int ret, len, offset;
193 struct timeval tv, *t;
195 t = NULL;
196 offset = 0;
197 len = sizeof(tapdisk_message_t);
199 if (timeout) {
200 tv.tv_sec = timeout;
201 tv.tv_usec = 0;
202 t = &tv;
203 }
205 memset(message, 0, sizeof(tapdisk_message_t));
207 while (offset < len) {
208 FD_ZERO(&readfds);
209 FD_SET(fd, &readfds);
211 /* we don't bother reinitializing tv. at worst, it will wait a
212 * bit more time than expected. */
214 ret = select(fd + 1, &readfds, NULL, NULL, t);
215 if (ret == -1)
216 break;
217 else if (FD_ISSET(fd, &readfds)) {
218 ret = read(fd, message + offset, len - offset);
219 if (ret <= 0)
220 break;
221 offset += ret;
222 } else
223 break;
224 }
226 if (offset != len) {
227 EPRINTF("failure reading message\n");
228 return -EIO;
229 }
231 DPRINTF("received '%s' message (uuid = %u)\n",
232 tapdisk_message_name(message->type), message->cookie);
234 return 0;
235 }
237 int
238 tapdisk_ipc_read(td_ipc_t *ipc)
239 {
240 int err;
241 td_vbd_t *vbd;
242 td_uuid_t uuid;
243 tapdisk_message_t message;
245 err = tapdisk_ipc_read_message(ipc->rfd, &message, 2);
246 if (err) {
247 tapdisk_server_check_state();
248 return err;
249 }
251 uuid = message.cookie;
252 vbd = tapdisk_server_get_vbd(uuid);
254 if (!vbd && message.type != TAPDISK_MESSAGE_PID) {
255 EPRINTF("received message for non-existing vbd: %u\n", uuid);
256 err = -EINVAL;
257 goto fail;
258 }
260 switch (message.type) {
261 case TAPDISK_MESSAGE_PID:
262 err = tapdisk_vbd_initialize(ipc->rfd, ipc->wfd, uuid);
264 memset(&message, 0, sizeof(tapdisk_message_t));
265 message.cookie = uuid;
267 if (!err) {
268 message.type = TAPDISK_MESSAGE_PID_RSP;
269 message.u.tapdisk_pid = getpid();
270 } else
271 message.type = TAPDISK_MESSAGE_ERROR;
273 return tapdisk_ipc_write_message(ipc->wfd, &message, 0);
275 case TAPDISK_MESSAGE_OPEN:
276 {
277 image_t image;
278 char *devname;
279 td_flag_t flags;
281 flags = 0;
283 if (message.u.params.flags & TAPDISK_MESSAGE_FLAG_RDONLY)
284 flags |= TD_OPEN_RDONLY;
285 if (message.u.params.flags & TAPDISK_MESSAGE_FLAG_SHARED)
286 flags |= TD_OPEN_SHAREABLE;
287 if (message.u.params.flags & TAPDISK_MESSAGE_FLAG_ADD_CACHE)
288 flags |= TD_OPEN_ADD_CACHE;
289 if (message.u.params.flags & TAPDISK_MESSAGE_FLAG_VHD_INDEX)
290 flags |= TD_OPEN_VHD_INDEX;
291 if (message.u.params.flags & TAPDISK_MESSAGE_FLAG_LOG_DIRTY)
292 flags |= TD_OPEN_LOG_DIRTY;
294 err = asprintf(&devname, "%s/%s%d",
295 BLKTAP_DEV_DIR, BLKTAP_DEV_NAME,
296 message.u.params.devnum);
297 if (err == -1)
298 goto fail;
300 err = tapdisk_vbd_open(vbd,
301 message.u.params.path,
302 message.drivertype,
303 message.u.params.storage,
304 devname, flags);
305 free(devname);
306 if (err)
307 goto fail;
309 err = tapdisk_vbd_get_image_info(vbd, &image);
310 if (err)
311 goto fail;
313 memset(&message, 0, sizeof(tapdisk_message_t));
314 message.cookie = uuid;
315 message.u.image.sectors = image.size;
316 message.u.image.sector_size = image.secsize;
317 message.u.image.info = image.info;
318 message.type = TAPDISK_MESSAGE_OPEN_RSP;
320 return tapdisk_ipc_write_message(ipc->wfd, &message, 0);
321 }
323 case TAPDISK_MESSAGE_PAUSE:
324 tapdisk_vbd_pause(vbd);
325 return 0; /* response written asynchronously */
327 case TAPDISK_MESSAGE_RESUME:
328 tapdisk_vbd_resume(vbd,
329 message.u.params.path,
330 message.drivertype);
331 return 0; /* response written asynchronously */
333 case TAPDISK_MESSAGE_CLOSE:
334 tapdisk_vbd_close(vbd);
335 return 0; /* response written asynchronously */
337 case TAPDISK_MESSAGE_EXIT:
338 return 0;
339 }
341 err = -EINVAL;
342 EPRINTF("received unrecognized message %s, uuid = %d\n",
343 tapdisk_message_name(message.type), uuid);
345 fail:
346 memset(&message, 0, sizeof(tapdisk_message_t));
347 message.cookie = uuid;
348 message.type = TAPDISK_MESSAGE_ERROR;
349 tapdisk_ipc_write_message(ipc->wfd, &message, 2);
350 tapdisk_server_check_state();
352 return -err;
353 }