debuggers.hg

view tools/blktap2/drivers/tapdisk-server.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 1cfd248d0fc8
children f2ef85551a09
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 <unistd.h>
31 #include <stdlib.h>
32 #include <sys/ioctl.h>
33 #include <sys/signal.h>
35 #define TAPDISK
36 #include "tapdisk-utils.h"
37 #include "tapdisk-server.h"
38 #include "tapdisk-driver.h"
39 #include "tapdisk-interface.h"
41 #define DBG(_level, _f, _a...) tlog_write(_level, _f, ##_a)
42 #define ERR(_err, _f, _a...) tlog_error(_err, _f, ##_a)
44 tapdisk_server_t server;
46 #define tapdisk_server_for_each_vbd(vbd, tmp) \
47 list_for_each_entry_safe(vbd, tmp, &server.vbds, next)
49 struct tap_disk *
50 tapdisk_server_find_driver_interface(int type)
51 {
52 int n;
54 n = sizeof(dtypes) / sizeof(struct disk_info_t *);
55 if (type >= n)
56 return NULL;
58 return dtypes[type]->drv;
59 }
61 td_image_t *
62 tapdisk_server_get_shared_image(td_image_t *image)
63 {
64 td_vbd_t *vbd, *tmpv;
65 td_image_t *img, *tmpi;
67 if (!td_flag_test(image->flags, TD_OPEN_SHAREABLE))
68 return NULL;
70 tapdisk_server_for_each_vbd(vbd, tmpv)
71 tapdisk_vbd_for_each_image(vbd, img, tmpi)
72 if (img->type == image->type &&
73 !strcmp(img->name, image->name))
74 return img;
76 return NULL;
77 }
79 td_vbd_t *
80 tapdisk_server_get_vbd(uint16_t uuid)
81 {
82 td_vbd_t *vbd, *tmp;
84 tapdisk_server_for_each_vbd(vbd, tmp)
85 if (vbd->uuid == uuid)
86 return vbd;
88 return NULL;
89 }
91 void
92 tapdisk_server_add_vbd(td_vbd_t *vbd)
93 {
94 list_add_tail(&vbd->next, &server.vbds);
95 }
97 void
98 tapdisk_server_remove_vbd(td_vbd_t *vbd)
99 {
100 list_del(&vbd->next);
101 INIT_LIST_HEAD(&vbd->next);
102 tapdisk_server_check_state();
103 }
105 void
106 tapdisk_server_queue_tiocb(struct tiocb *tiocb)
107 {
108 tapdisk_queue_tiocb(&server.aio_queue, tiocb);
109 }
111 void
112 tapdisk_server_debug(void)
113 {
114 td_vbd_t *vbd, *tmp;
116 tapdisk_debug_queue(&server.aio_queue);
118 tapdisk_server_for_each_vbd(vbd, tmp)
119 tapdisk_vbd_debug(vbd);
121 tlog_flush();
122 }
124 void
125 tapdisk_server_check_state(void)
126 {
127 if (list_empty(&server.vbds))
128 server.run = 0;
129 }
131 event_id_t
132 tapdisk_server_register_event(char mode, int fd,
133 int timeout, event_cb_t cb, void *data)
134 {
135 return scheduler_register_event(&server.scheduler,
136 mode, fd, timeout, cb, data);
137 }
139 void
140 tapdisk_server_unregister_event(event_id_t event)
141 {
142 return scheduler_unregister_event(&server.scheduler, event);
143 }
145 void
146 tapdisk_server_set_max_timeout(int seconds)
147 {
148 scheduler_set_max_timeout(&server.scheduler, seconds);
149 }
151 static void
152 tapdisk_server_assert_locks(void)
153 {
155 }
157 static void
158 tapdisk_server_set_retry_timeout(void)
159 {
160 td_vbd_t *vbd, *tmp;
162 tapdisk_server_for_each_vbd(vbd, tmp)
163 if (tapdisk_vbd_retry_needed(vbd)) {
164 tapdisk_server_set_max_timeout(TD_VBD_RETRY_INTERVAL);
165 return;
166 }
167 }
169 static void
170 tapdisk_server_check_progress(void)
171 {
172 struct timeval now;
173 td_vbd_t *vbd, *tmp;
175 gettimeofday(&now, NULL);
177 tapdisk_server_for_each_vbd(vbd, tmp)
178 tapdisk_vbd_check_progress(vbd);
179 }
181 static void
182 tapdisk_server_submit_tiocbs(void)
183 {
184 tapdisk_submit_all_tiocbs(&server.aio_queue);
185 }
187 static void
188 tapdisk_server_kick_responses(void)
189 {
190 int n;
191 td_vbd_t *vbd, *tmp;
193 tapdisk_server_for_each_vbd(vbd, tmp)
194 tapdisk_vbd_kick(vbd);
195 }
197 static void
198 tapdisk_server_check_vbds(void)
199 {
200 td_vbd_t *vbd, *tmp;
202 tapdisk_server_for_each_vbd(vbd, tmp)
203 tapdisk_vbd_check_state(vbd);
204 }
206 static void
207 tapdisk_server_stop_vbds(void)
208 {
209 td_vbd_t *vbd, *tmp;
211 tapdisk_server_for_each_vbd(vbd, tmp)
212 tapdisk_vbd_kill_queue(vbd);
213 }
215 static void
216 tapdisk_server_send_error(const char *message)
217 {
218 td_vbd_t *vbd, *tmp;
220 tapdisk_server_for_each_vbd(vbd, tmp)
221 tapdisk_ipc_write_error(&vbd->ipc, message);
222 }
224 static void
225 tapdisk_server_aio_queue_event(event_id_t id, char mode, void *private)
226 {
227 tapdisk_complete_tiocbs(&server.aio_queue);
228 }
230 static void
231 tapdisk_server_free_aio_queue(void)
232 {
233 tapdisk_server_unregister_event(server.aio_queue_event_id);
234 tapdisk_free_queue(&server.aio_queue);
235 }
237 static int
238 tapdisk_server_init_ipc(const char *read, const char *write)
239 {
240 return tapdisk_ipc_open(&server.ipc, read, write);
241 }
243 static void
244 tapdisk_server_close_ipc(void)
245 {
246 tapdisk_ipc_close(&server.ipc);
247 }
249 static int
250 tapdisk_server_initialize_aio_queue(void)
251 {
252 int err;
253 event_id_t id;
255 err = tapdisk_init_queue(&server.aio_queue,
256 TAPDISK_TIOCBS, 0, NULL);
257 if (err)
258 return err;
260 id = tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
261 server.aio_queue.poll_fd, 0,
262 tapdisk_server_aio_queue_event,
263 NULL);
264 if (id < 0) {
265 tapdisk_free_queue(&server.aio_queue);
266 return id;
267 }
269 server.aio_queue_event_id = id;
271 return 0;
272 }
274 static void
275 tapdisk_server_close(void)
276 {
277 tapdisk_server_free_aio_queue();
278 tapdisk_server_close_ipc();
279 }
281 static void
282 __tapdisk_server_run(void)
283 {
284 int ret;
286 while (server.run) {
287 tapdisk_server_assert_locks();
288 tapdisk_server_set_retry_timeout();
289 tapdisk_server_check_progress();
291 ret = scheduler_wait_for_events(&server.scheduler);
292 if (ret < 0)
293 DBG(TLOG_WARN, "server wait returned %d\n", ret);
295 tapdisk_server_check_vbds();
296 tapdisk_server_submit_tiocbs();
297 tapdisk_server_kick_responses();
298 }
299 }
301 static void
302 tapdisk_server_signal_handler(int signal)
303 {
304 td_vbd_t *vbd, *tmp;
305 static int xfsz_error_sent = 0;
307 switch (signal) {
308 case SIGBUS:
309 case SIGINT:
310 tapdisk_server_for_each_vbd(vbd, tmp)
311 tapdisk_vbd_close(vbd);
312 break;
314 case SIGXFSZ:
315 ERR(EFBIG, "received SIGXFSZ");
316 tapdisk_server_stop_vbds();
317 if (xfsz_error_sent)
318 break;
320 tapdisk_server_send_error("received SIGXFSZ, closing queues");
321 xfsz_error_sent = 1;
322 break;
324 case SIGUSR1:
325 tapdisk_server_debug();
326 break;
327 }
328 }
330 int
331 tapdisk_server_initialize(const char *read, const char *write)
332 {
333 int err;
335 memset(&server, 0, sizeof(tapdisk_server_t));
336 INIT_LIST_HEAD(&server.vbds);
338 scheduler_initialize(&server.scheduler);
340 err = tapdisk_server_init_ipc(read, write);
341 if (err)
342 goto fail;
344 err = tapdisk_server_initialize_aio_queue();
345 if (err)
346 goto fail;
348 server.run = 1;
350 return 0;
352 fail:
353 tapdisk_server_close_ipc();
354 return err;
355 }
357 int
358 tapdisk_server_run()
359 {
360 int err;
362 err = tapdisk_set_resource_limits();
363 if (err)
364 return err;
366 signal(SIGBUS, tapdisk_server_signal_handler);
367 signal(SIGINT, tapdisk_server_signal_handler);
368 signal(SIGUSR1, tapdisk_server_signal_handler);
369 signal(SIGXFSZ, tapdisk_server_signal_handler);
371 __tapdisk_server_run();
372 tapdisk_server_close();
374 return 0;
375 }