Statistics
| Branch: | Revision:

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
}