root / drivers / tapdisk-server.c @ abdb293f
History | View | Annotate | Download (8.4 kB)
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 |
|
29 |
#ifdef HAVE_CONFIG_H
|
30 |
#include "config.h" |
31 |
#endif
|
32 |
|
33 |
#include <stdio.h> |
34 |
#include <errno.h> |
35 |
#include <unistd.h> |
36 |
#include <stdlib.h> |
37 |
#include <sys/ioctl.h> |
38 |
#include <sys/signal.h> |
39 |
|
40 |
#include "tapdisk-syslog.h" |
41 |
#include "tapdisk-server.h" |
42 |
#include "tapdisk-driver.h" |
43 |
#include "tapdisk-interface.h" |
44 |
#include "tapdisk-log.h" |
45 |
|
46 |
#define DBG(_level, _f, _a...) tlog_write(_level, _f, ##_a) |
47 |
#define ERR(_err, _f, _a...) tlog_error(_err, _f, ##_a) |
48 |
|
49 |
#define TAPDISK_TIOCBS (TAPDISK_DATA_REQUESTS + 50) |
50 |
|
51 |
typedef struct tapdisk_server { |
52 |
int run;
|
53 |
struct list_head vbds;
|
54 |
scheduler_t scheduler; |
55 |
struct tqueue aio_queue;
|
56 |
char *name;
|
57 |
char *ident;
|
58 |
int facility;
|
59 |
} tapdisk_server_t; |
60 |
|
61 |
static tapdisk_server_t server;
|
62 |
|
63 |
#define tapdisk_server_for_each_vbd(vbd, tmp) \
|
64 |
list_for_each_entry_safe(vbd, tmp, &server.vbds, next) |
65 |
|
66 |
td_image_t * |
67 |
tapdisk_server_get_shared_image(td_image_t *image) |
68 |
{ |
69 |
td_vbd_t *vbd, *tmpv; |
70 |
td_image_t *img, *tmpi; |
71 |
|
72 |
if (!td_flag_test(image->flags, TD_OPEN_SHAREABLE))
|
73 |
return NULL; |
74 |
|
75 |
tapdisk_server_for_each_vbd(vbd, tmpv) |
76 |
tapdisk_vbd_for_each_image(vbd, img, tmpi) |
77 |
if (img->type == image->type &&
|
78 |
!strcmp(img->name, image->name)) |
79 |
return img;
|
80 |
|
81 |
return NULL; |
82 |
} |
83 |
|
84 |
struct list_head *
|
85 |
tapdisk_server_get_all_vbds(void)
|
86 |
{ |
87 |
return &server.vbds;
|
88 |
} |
89 |
|
90 |
td_vbd_t * |
91 |
tapdisk_server_get_vbd(uint16_t uuid) |
92 |
{ |
93 |
td_vbd_t *vbd, *tmp; |
94 |
|
95 |
tapdisk_server_for_each_vbd(vbd, tmp) |
96 |
if (vbd->uuid == uuid)
|
97 |
return vbd;
|
98 |
|
99 |
return NULL; |
100 |
} |
101 |
|
102 |
void
|
103 |
tapdisk_server_add_vbd(td_vbd_t *vbd) |
104 |
{ |
105 |
list_add_tail(&vbd->next, &server.vbds); |
106 |
} |
107 |
|
108 |
void
|
109 |
tapdisk_server_remove_vbd(td_vbd_t *vbd) |
110 |
{ |
111 |
list_del(&vbd->next); |
112 |
INIT_LIST_HEAD(&vbd->next); |
113 |
tapdisk_server_check_state(); |
114 |
} |
115 |
|
116 |
void
|
117 |
tapdisk_server_queue_tiocb(struct tiocb *tiocb)
|
118 |
{ |
119 |
tapdisk_queue_tiocb(&server.aio_queue, tiocb); |
120 |
} |
121 |
|
122 |
void
|
123 |
tapdisk_server_debug(void)
|
124 |
{ |
125 |
td_vbd_t *vbd, *tmp; |
126 |
|
127 |
tapdisk_debug_queue(&server.aio_queue); |
128 |
|
129 |
tapdisk_server_for_each_vbd(vbd, tmp) |
130 |
tapdisk_vbd_debug(vbd); |
131 |
|
132 |
DBG(TLOG_INFO, "debug log completed\n");
|
133 |
tlog_precious(); |
134 |
} |
135 |
|
136 |
void
|
137 |
tapdisk_server_check_state(void)
|
138 |
{ |
139 |
if (list_empty(&server.vbds))
|
140 |
server.run = 0;
|
141 |
} |
142 |
|
143 |
event_id_t |
144 |
tapdisk_server_register_event(char mode, int fd, |
145 |
int timeout, event_cb_t cb, void *data) |
146 |
{ |
147 |
return scheduler_register_event(&server.scheduler,
|
148 |
mode, fd, timeout, cb, data); |
149 |
} |
150 |
|
151 |
void
|
152 |
tapdisk_server_unregister_event(event_id_t event) |
153 |
{ |
154 |
return scheduler_unregister_event(&server.scheduler, event);
|
155 |
} |
156 |
|
157 |
void
|
158 |
tapdisk_server_mask_event(event_id_t event, int masked)
|
159 |
{ |
160 |
return scheduler_mask_event(&server.scheduler, event, masked);
|
161 |
} |
162 |
|
163 |
void
|
164 |
tapdisk_server_set_max_timeout(int seconds)
|
165 |
{ |
166 |
scheduler_set_max_timeout(&server.scheduler, seconds); |
167 |
} |
168 |
|
169 |
static void |
170 |
tapdisk_server_assert_locks(void)
|
171 |
{ |
172 |
|
173 |
} |
174 |
|
175 |
static void |
176 |
tapdisk_server_set_retry_timeout(void)
|
177 |
{ |
178 |
td_vbd_t *vbd, *tmp; |
179 |
|
180 |
tapdisk_server_for_each_vbd(vbd, tmp) |
181 |
if (tapdisk_vbd_retry_needed(vbd)) {
|
182 |
tapdisk_server_set_max_timeout(TD_VBD_RETRY_INTERVAL); |
183 |
return;
|
184 |
} |
185 |
} |
186 |
|
187 |
static void |
188 |
tapdisk_server_check_progress(void)
|
189 |
{ |
190 |
struct timeval now;
|
191 |
td_vbd_t *vbd, *tmp; |
192 |
|
193 |
gettimeofday(&now, NULL);
|
194 |
|
195 |
tapdisk_server_for_each_vbd(vbd, tmp) |
196 |
tapdisk_vbd_check_progress(vbd); |
197 |
} |
198 |
|
199 |
static void |
200 |
tapdisk_server_submit_tiocbs(void)
|
201 |
{ |
202 |
tapdisk_submit_all_tiocbs(&server.aio_queue); |
203 |
} |
204 |
|
205 |
static void |
206 |
tapdisk_server_kick_responses(void)
|
207 |
{ |
208 |
td_vbd_t *vbd, *tmp; |
209 |
|
210 |
tapdisk_server_for_each_vbd(vbd, tmp) |
211 |
tapdisk_vbd_kick(vbd); |
212 |
} |
213 |
|
214 |
static void |
215 |
tapdisk_server_check_vbds(void)
|
216 |
{ |
217 |
td_vbd_t *vbd, *tmp; |
218 |
|
219 |
tapdisk_server_for_each_vbd(vbd, tmp) |
220 |
tapdisk_vbd_check_state(vbd); |
221 |
} |
222 |
|
223 |
static int |
224 |
tapdisk_server_recheck_vbds(void)
|
225 |
{ |
226 |
td_vbd_t *vbd, *tmp; |
227 |
int rv = 0; |
228 |
|
229 |
tapdisk_server_for_each_vbd(vbd, tmp) |
230 |
rv += tapdisk_vbd_recheck_state(vbd); |
231 |
|
232 |
return rv;
|
233 |
} |
234 |
|
235 |
static void |
236 |
tapdisk_server_stop_vbds(void)
|
237 |
{ |
238 |
td_vbd_t *vbd, *tmp; |
239 |
|
240 |
tapdisk_server_for_each_vbd(vbd, tmp) |
241 |
tapdisk_vbd_kill_queue(vbd); |
242 |
} |
243 |
|
244 |
static int |
245 |
tapdisk_server_init_aio(void)
|
246 |
{ |
247 |
return tapdisk_init_queue(&server.aio_queue, TAPDISK_TIOCBS,
|
248 |
TIO_DRV_LIO, NULL);
|
249 |
} |
250 |
|
251 |
static void |
252 |
tapdisk_server_close_aio(void)
|
253 |
{ |
254 |
tapdisk_free_queue(&server.aio_queue); |
255 |
} |
256 |
|
257 |
int
|
258 |
tapdisk_server_openlog(const char *name, int options, int facility) |
259 |
{ |
260 |
server.facility = facility; |
261 |
server.name = strdup(name); |
262 |
server.ident = tapdisk_syslog_ident(name); |
263 |
|
264 |
if (!server.name || !server.ident)
|
265 |
return -errno;
|
266 |
|
267 |
openlog(server.ident, options, facility); |
268 |
|
269 |
return 0; |
270 |
} |
271 |
|
272 |
void
|
273 |
tapdisk_server_closelog(void)
|
274 |
{ |
275 |
closelog(); |
276 |
|
277 |
free(server.name); |
278 |
server.name = NULL;
|
279 |
|
280 |
free(server.ident); |
281 |
server.ident = NULL;
|
282 |
} |
283 |
|
284 |
static int |
285 |
tapdisk_server_open_tlog(void)
|
286 |
{ |
287 |
int err = 0; |
288 |
|
289 |
if (server.name)
|
290 |
err = tlog_open(server.name, server.facility, TLOG_WARN); |
291 |
|
292 |
return err;
|
293 |
} |
294 |
|
295 |
static void |
296 |
tapdisk_server_close_tlog(void)
|
297 |
{ |
298 |
tlog_close(); |
299 |
} |
300 |
|
301 |
static void |
302 |
tapdisk_server_close(void)
|
303 |
{ |
304 |
tapdisk_server_close_tlog(); |
305 |
tapdisk_server_close_aio(); |
306 |
} |
307 |
|
308 |
void
|
309 |
tapdisk_server_iterate(void)
|
310 |
{ |
311 |
int ret;
|
312 |
|
313 |
tapdisk_server_assert_locks(); |
314 |
tapdisk_server_set_retry_timeout(); |
315 |
tapdisk_server_check_progress(); |
316 |
|
317 |
ret = scheduler_wait_for_events(&server.scheduler); |
318 |
if (ret < 0) |
319 |
DBG(TLOG_WARN, "server wait returned %d\n", ret);
|
320 |
|
321 |
tapdisk_server_check_vbds(); |
322 |
do {
|
323 |
tapdisk_server_submit_tiocbs(); |
324 |
tapdisk_server_kick_responses(); |
325 |
|
326 |
ret = tapdisk_server_recheck_vbds(); |
327 |
} while (ret);
|
328 |
} |
329 |
|
330 |
static void |
331 |
__tapdisk_server_run(void)
|
332 |
{ |
333 |
while (server.run)
|
334 |
tapdisk_server_iterate(); |
335 |
} |
336 |
|
337 |
static void |
338 |
tapdisk_server_signal_handler(int signal)
|
339 |
{ |
340 |
td_vbd_t *vbd, *tmp; |
341 |
static int xfsz_error_sent = 0; |
342 |
|
343 |
switch (signal) {
|
344 |
case SIGBUS:
|
345 |
case SIGINT:
|
346 |
tapdisk_server_for_each_vbd(vbd, tmp) |
347 |
tapdisk_vbd_close(vbd); |
348 |
break;
|
349 |
|
350 |
case SIGXFSZ:
|
351 |
ERR(EFBIG, "received SIGXFSZ");
|
352 |
tapdisk_server_stop_vbds(); |
353 |
if (xfsz_error_sent)
|
354 |
break;
|
355 |
|
356 |
xfsz_error_sent = 1;
|
357 |
break;
|
358 |
|
359 |
case SIGUSR1:
|
360 |
DBG(TLOG_INFO, "debugging on signal %d\n", signal);
|
361 |
tapdisk_server_debug(); |
362 |
break;
|
363 |
} |
364 |
} |
365 |
|
366 |
int
|
367 |
tapdisk_server_init(void)
|
368 |
{ |
369 |
memset(&server, 0, sizeof(server)); |
370 |
INIT_LIST_HEAD(&server.vbds); |
371 |
|
372 |
scheduler_initialize(&server.scheduler); |
373 |
|
374 |
return 0; |
375 |
} |
376 |
|
377 |
int
|
378 |
tapdisk_server_complete(void)
|
379 |
{ |
380 |
int err;
|
381 |
|
382 |
err = tapdisk_server_init_aio(); |
383 |
if (err)
|
384 |
goto fail;
|
385 |
|
386 |
err = tapdisk_server_open_tlog(); |
387 |
if (err)
|
388 |
goto fail;
|
389 |
|
390 |
server.run = 1;
|
391 |
|
392 |
return 0; |
393 |
|
394 |
fail:
|
395 |
tapdisk_server_close_tlog(); |
396 |
tapdisk_server_close_aio(); |
397 |
return err;
|
398 |
} |
399 |
|
400 |
int
|
401 |
tapdisk_server_initialize(const char *read, const char *write) |
402 |
{ |
403 |
int err;
|
404 |
|
405 |
tapdisk_server_init(); |
406 |
|
407 |
err = tapdisk_server_complete(); |
408 |
if (err)
|
409 |
goto fail;
|
410 |
|
411 |
return 0; |
412 |
|
413 |
fail:
|
414 |
tapdisk_server_close(); |
415 |
return err;
|
416 |
} |
417 |
|
418 |
int
|
419 |
tapdisk_server_run() |
420 |
{ |
421 |
int err;
|
422 |
|
423 |
err = tapdisk_set_resource_limits(); |
424 |
if (err)
|
425 |
return err;
|
426 |
|
427 |
signal(SIGBUS, tapdisk_server_signal_handler); |
428 |
signal(SIGINT, tapdisk_server_signal_handler); |
429 |
signal(SIGUSR1, tapdisk_server_signal_handler); |
430 |
signal(SIGXFSZ, tapdisk_server_signal_handler); |
431 |
|
432 |
__tapdisk_server_run(); |
433 |
tapdisk_server_close(); |
434 |
|
435 |
return 0; |
436 |
} |