~ubuntu-branches/ubuntu/trusty/cluster-glue/trusty

« back to all changes in this revision

Viewing changes to lib/stonith/sbd-md.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-10-18 05:14:00 UTC
  • mfrom: (5.2.7 sid)
  • Revision ID: james.westby@ubuntu.com-20111018051400-cqhq161ro23f2t9g
Tags: 1.0.7+hg2618-2ubuntu1
* Merge from Debian testing, remaining changes:
  - debian/rules: Add -V argument to dh_makeshlibs.
  - Enable Upstart RA:
    + debian/cluster-glue.install: Install upstart RA.
    + debian/control: Build-depends on libdbus-glib-1-dev and libdbus-1-dev.
    + debian/patches/raexecupstart.patch: Fix deadlock

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2008 Lars Marowsky-Bree <lmb@suse.de>
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2.1 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This software is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public
 
15
 * License along with this library; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 */
 
18
 
 
19
#include <signal.h>
 
20
#include <errno.h>
 
21
#include <sys/types.h>
 
22
#include <sys/wait.h>
 
23
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <unistd.h>
 
26
#include <asm/unistd.h>
 
27
#include <ctype.h>
 
28
#include <string.h>
 
29
#include <syslog.h>
 
30
#include <sys/types.h>
 
31
#include <sys/stat.h>
 
32
#include <sys/ptrace.h>
 
33
#include <fcntl.h>
 
34
#include <time.h>
 
35
#include <clplumbing/cl_log.h>
 
36
#include <clplumbing/coredumps.h>
 
37
#include <clplumbing/realtime.h>
 
38
#include <clplumbing/cl_reboot.h>
 
39
#include <clplumbing/setproctitle.h>
 
40
#include <malloc.h>
 
41
#include <time.h>
 
42
#include <sys/utsname.h>
 
43
#include <sys/ioctl.h>
 
44
#include <linux/types.h>
 
45
#include <linux/watchdog.h>
 
46
#include <linux/fs.h>
 
47
 
 
48
#include "sbd.h"
 
49
 
 
50
struct servants_list_item *servants_leader = NULL;
 
51
 
 
52
static int      servant_count   = 0;
 
53
static int      servant_restart_interval = 3600;
 
54
 
 
55
/* signals reserved for multi-disk sbd */
 
56
#define SIG_LIVENESS (SIGRTMIN + 1)     /* report liveness of the disk */
 
57
#define SIG_EXITREQ  (SIGRTMIN + 2)     /* exit request to inquisitor */
 
58
#define SIG_TEST     (SIGRTMIN + 3)     /* trigger self test */
 
59
#define SIG_RESTART  (SIGRTMIN + 4)     /* trigger restart of all failed disk */
 
60
/* FIXME: should add dynamic check of SIG_XX >= SIGRTMAX */
 
61
 
 
62
/* Debug Helper */
 
63
#if 0
 
64
#define DBGPRINT(...) fprintf(stderr, __VA_ARGS__)
 
65
#else
 
66
#define DBGPRINT(...) do {} while (0)
 
67
#endif
 
68
 
 
69
int quorum_write(int good_servants)
 
70
{
 
71
        return (good_servants > servant_count/2);       
 
72
}
 
73
 
 
74
int quorum_read(int good_servants)
 
75
{
 
76
        if (servant_count >= 3) 
 
77
                return (good_servants > servant_count/2);
 
78
        else
 
79
                return (good_servants >= 1);
 
80
}
 
81
 
 
82
int assign_servant(const char* devname, functionp_t functionp, const void* argp)
 
83
{
 
84
        pid_t pid = 0;
 
85
        int rc = 0;
 
86
 
 
87
        DBGPRINT("fork servant for %s\n", devname);
 
88
        pid = fork();
 
89
        if (pid == 0) {         /* child */
 
90
                maximize_priority();
 
91
                rc = (*functionp)(devname, argp);
 
92
                if (rc == -1)
 
93
                        exit(1);
 
94
                else
 
95
                        exit(0);
 
96
        } else if (pid != -1) {         /* parent */
 
97
                return pid;
 
98
        } else {
 
99
                cl_log(LOG_ERR,"Failed to fork servant");
 
100
                exit(1);
 
101
        }
 
102
}
 
103
 
 
104
int init_devices()
 
105
{
 
106
        int rc = 0;
 
107
        int devfd;
 
108
        struct servants_list_item *s;
 
109
 
 
110
        for (s = servants_leader; s; s = s->next) {
 
111
                fprintf(stdout, "Initializing device %s\n",
 
112
                                s->devname);
 
113
                devfd = open_device(s->devname);
 
114
                if (devfd == -1) {
 
115
                        return -1;
 
116
                }
 
117
                rc = init_device(devfd);
 
118
                close(devfd);
 
119
                if (rc == -1) {
 
120
                        fprintf(stderr, "Failed to init device %s\n", s->devname);
 
121
                        return rc;
 
122
                }
 
123
                fprintf(stdout, "Device %s is initialized.\n", s->devname);
 
124
        }
 
125
        return 0;
 
126
}
 
127
 
 
128
int slot_msg_wrapper(const char* devname, const void* argp)
 
129
{
 
130
        int rc = 0;
 
131
        int devfd;
 
132
        const struct slot_msg_arg_t* arg = (const struct slot_msg_arg_t*)argp;
 
133
 
 
134
        devfd = open_device(devname);
 
135
        if (devfd == -1) 
 
136
                return -1;
 
137
        rc = slot_msg(devfd, arg->name, arg->msg);
 
138
        close(devfd);
 
139
        return rc;
 
140
}
 
141
 
 
142
int slot_ping_wrapper(const char* devname, const void* argp)
 
143
{
 
144
        int rc = 0;
 
145
        const char* name = (const char*)argp;
 
146
        int devfd;
 
147
 
 
148
        devfd = open_device(devname);
 
149
        if (devfd == -1)
 
150
                return -1;
 
151
        rc = slot_ping(devfd, name);
 
152
        close(devfd);
 
153
        return rc;
 
154
}
 
155
 
 
156
int allocate_slots(const char *name)
 
157
{
 
158
        int rc = 0;
 
159
        int devfd;
 
160
        struct servants_list_item *s;
 
161
 
 
162
        for (s = servants_leader; s; s = s->next) {
 
163
                fprintf(stdout, "Trying to allocate slot for %s on device %s.\n", 
 
164
                                name,
 
165
                                s->devname);
 
166
                devfd = open_device(s->devname);
 
167
                if (devfd == -1) {
 
168
                        return -1;
 
169
                }
 
170
                rc = slot_allocate(devfd, name);
 
171
                close(devfd);
 
172
                if (rc == -1)
 
173
                        return rc;
 
174
                fprintf(stdout, "Slot for %s has been allocated on %s.\n",
 
175
                                name,
 
176
                                s->devname);
 
177
        }
 
178
        return 0;
 
179
}
 
180
 
 
181
int list_slots()
 
182
{
 
183
        int rc = 0;
 
184
        struct servants_list_item *s;
 
185
        int devfd;
 
186
 
 
187
        for (s = servants_leader; s; s = s->next) {
 
188
                DBGPRINT("list slots on device %s\n", s->devname);
 
189
                devfd = open_device(s->devname);
 
190
                if (devfd == -1)
 
191
                        return -1;
 
192
                rc = slot_list(devfd);
 
193
                close(devfd);
 
194
                if (rc == -1)
 
195
                        return rc;
 
196
        }
 
197
        return 0;
 
198
}
 
199
 
 
200
int ping_via_slots(const char *name)
 
201
{
 
202
        int sig = 0;
 
203
        pid_t pid = 0;
 
204
        int status = 0;
 
205
        int servants_finished = 0;
 
206
        sigset_t procmask;
 
207
        siginfo_t sinfo;
 
208
        struct servants_list_item *s;
 
209
 
 
210
        DBGPRINT("you shall know no fear\n");
 
211
        sigemptyset(&procmask);
 
212
        sigaddset(&procmask, SIGCHLD);
 
213
        sigprocmask(SIG_BLOCK, &procmask, NULL);
 
214
 
 
215
        for (s = servants_leader; s; s = s->next) {
 
216
                s->pid = assign_servant(s->devname, &slot_ping_wrapper, (const void*)name);
 
217
        }
 
218
 
 
219
        while (servants_finished < servant_count) {
 
220
                sig = sigwaitinfo(&procmask, &sinfo);
 
221
                DBGPRINT("get signal %d\n", sig);
 
222
                if (sig == SIGCHLD) {
 
223
                        while ((pid = wait(&status))) {
 
224
                                if (pid == -1 && errno == ECHILD) {
 
225
                                        break;
 
226
                                } else {
 
227
                                        s = lookup_servant_by_pid(pid);
 
228
                                        if (s) {
 
229
                                                DBGPRINT
 
230
                                                    ("A ping is delivered to %s via %s. ",
 
231
                                                     name, s->devname);
 
232
                                                if (!status)
 
233
                                                        DBGPRINT
 
234
                                                            ("They responed to the emporer\n");
 
235
                                                else
 
236
                                                        DBGPRINT
 
237
                                                            ("There's no response\n");
 
238
                                                servants_finished++;
 
239
                                        }
 
240
                                }
 
241
                        }
 
242
                }
 
243
                DBGPRINT("signal %d handled\n", sig);
 
244
        }
 
245
        return 0;
 
246
}
 
247
 
 
248
int servant(const char *diskname, const void* argp)
 
249
{
 
250
        struct sector_mbox_s *s_mbox = NULL;
 
251
        int mbox;
 
252
        int rc = 0;
 
253
        time_t t0, t1, latency;
 
254
        union sigval signal_value;
 
255
        sigset_t servant_masks;
 
256
        int devfd;
 
257
        pid_t ppid;
 
258
 
 
259
        if (!diskname) {
 
260
                cl_log(LOG_ERR, "Empty disk name %s.", diskname);
 
261
                return -1;
 
262
        }
 
263
 
 
264
        /* Block most of the signals */
 
265
        sigfillset(&servant_masks);
 
266
        sigdelset(&servant_masks, SIGKILL);
 
267
        sigdelset(&servant_masks, SIGFPE);
 
268
        sigdelset(&servant_masks, SIGILL);
 
269
        sigdelset(&servant_masks, SIGSEGV);
 
270
        sigdelset(&servant_masks, SIGBUS);
 
271
        sigdelset(&servant_masks, SIGALRM);
 
272
        /* FIXME: check error */
 
273
        sigprocmask(SIG_SETMASK, &servant_masks, NULL);
 
274
 
 
275
        devfd = open_device(diskname);
 
276
        if (devfd == -1) {
 
277
                return -1;
 
278
        }
 
279
 
 
280
        mbox = slot_allocate(devfd, local_uname);
 
281
        if (mbox < 0) {
 
282
                cl_log(LOG_ERR,
 
283
                       "No slot allocated, and automatic allocation failed for disk %s.",
 
284
                       diskname);
 
285
                rc = -1;
 
286
                goto out;
 
287
        }
 
288
        cl_log(LOG_INFO, "Monitoring slot %d on disk %s", mbox, diskname);
 
289
        set_proc_title("sbd: watcher: %s - slot: %d", diskname, mbox);
 
290
 
 
291
        s_mbox = sector_alloc();
 
292
        if (mbox_write(devfd, mbox, s_mbox) < 0) {
 
293
                rc = -1;
 
294
                goto out;
 
295
        }
 
296
 
 
297
        memset(&signal_value, 0, sizeof(signal_value));
 
298
 
 
299
        while (1) {
 
300
                t0 = time(NULL);
 
301
                sleep(timeout_loop);
 
302
 
 
303
                ppid = getppid();
 
304
 
 
305
                if (ppid == 1) {
 
306
                        /* Our parent died unexpectedly. Triggering
 
307
                         * self-fence. */
 
308
                        do_reset();
 
309
                }
 
310
 
 
311
                if (mbox_read(devfd, mbox, s_mbox) < 0) {
 
312
                        cl_log(LOG_ERR, "mbox read failed in servant.");
 
313
                        exit(1);
 
314
                }
 
315
 
 
316
                if (s_mbox->cmd > 0) {
 
317
                        cl_log(LOG_INFO,
 
318
                               "Received command %s from %s on disk %s",
 
319
                               char2cmd(s_mbox->cmd), s_mbox->from, diskname);
 
320
 
 
321
                        switch (s_mbox->cmd) {
 
322
                        case SBD_MSG_TEST:
 
323
                                memset(s_mbox, 0, sizeof(*s_mbox));
 
324
                                mbox_write(devfd, mbox, s_mbox);
 
325
                                sigqueue(ppid, SIG_TEST, signal_value);
 
326
                                break;
 
327
                        case SBD_MSG_RESET:
 
328
                                do_reset();
 
329
                                break;
 
330
                        case SBD_MSG_OFF:
 
331
                                do_off();
 
332
                                break;
 
333
                        case SBD_MSG_EXIT:
 
334
                                sigqueue(ppid, SIG_EXITREQ, signal_value);
 
335
                                break;
 
336
                        case SBD_MSG_CRASHDUMP:
 
337
                                do_crashdump();
 
338
                                break;
 
339
                        default:
 
340
                                /* FIXME:
 
341
                                   An "unknown" message might result
 
342
                                   from a partial write.
 
343
                                   log it and clear the slot.
 
344
                                 */
 
345
                                cl_log(LOG_ERR, "Unknown message on disk %s",
 
346
                                       diskname);
 
347
                                memset(s_mbox, 0, sizeof(*s_mbox));
 
348
                                mbox_write(devfd, mbox, s_mbox);
 
349
                                break;
 
350
                        }
 
351
                }
 
352
                sigqueue(ppid, SIG_LIVENESS, signal_value);
 
353
 
 
354
                t1 = time(NULL);
 
355
                latency = t1 - t0;
 
356
                if (timeout_watchdog_warn && (latency > timeout_watchdog_warn)) {
 
357
                        cl_log(LOG_WARNING,
 
358
                               "Latency: %d exceeded threshold %d on disk %s",
 
359
                               (int)latency, (int)timeout_watchdog_warn,
 
360
                               diskname);
 
361
                } else if (debug) {
 
362
                        cl_log(LOG_INFO, "Latency: %d on disk %s", (int)latency,
 
363
                               diskname);
 
364
                }
 
365
        }
 
366
 out:
 
367
        free(s_mbox);
 
368
        close(devfd);
 
369
        devfd = -1;
 
370
        return rc;
 
371
}
 
372
 
 
373
void recruit_servant(const char *devname, pid_t pid)
 
374
{
 
375
        struct servants_list_item *s = servants_leader;
 
376
        struct servants_list_item *newbie;
 
377
 
 
378
        newbie = malloc(sizeof(*newbie));
 
379
        if (!newbie) {
 
380
                fprintf(stderr, "malloc failed in recruit_servant.");
 
381
                exit(1);
 
382
        }
 
383
        memset(newbie, 0, sizeof(*newbie));
 
384
        newbie->devname = strdup(devname);
 
385
        newbie->pid = pid;
 
386
 
 
387
        if (!s) {
 
388
                servants_leader = newbie;
 
389
        } else {
 
390
                while (s->next)
 
391
                        s = s->next;
 
392
                s->next = newbie;
 
393
        }
 
394
 
 
395
        servant_count++;
 
396
}
 
397
 
 
398
struct servants_list_item *lookup_servant_by_dev(const char *devname)
 
399
{
 
400
        struct servants_list_item *s;
 
401
 
 
402
        for (s = servants_leader; s; s = s->next) {
 
403
                if (strncasecmp(s->devname, devname, strlen(s->devname)))
 
404
                        break;
 
405
        }
 
406
        return s;
 
407
}
 
408
 
 
409
struct servants_list_item *lookup_servant_by_pid(pid_t pid)
 
410
{
 
411
        struct servants_list_item *s;
 
412
 
 
413
        for (s = servants_leader; s; s = s->next) {
 
414
                if (s->pid == pid)
 
415
                        break;
 
416
        }
 
417
        return s;
 
418
}
 
419
 
 
420
int check_all_dead(void)
 
421
{
 
422
        struct servants_list_item *s;
 
423
        int r = 0;
 
424
        union sigval svalue;
 
425
 
 
426
        for (s = servants_leader; s; s = s->next) {
 
427
                if (s->pid != 0) {
 
428
                        r = sigqueue(s->pid, 0, svalue);
 
429
                        if (r == -1 && errno == ESRCH)
 
430
                                continue;
 
431
                        return 0;
 
432
                }
 
433
        }
 
434
        return 1;
 
435
}
 
436
 
 
437
 
 
438
void servants_start(void)
 
439
{
 
440
        struct servants_list_item *s;
 
441
        int r = 0;
 
442
        union sigval svalue;
 
443
 
 
444
        for (s = servants_leader; s; s = s->next) {
 
445
                if (s->pid != 0) {
 
446
                        r = sigqueue(s->pid, 0, svalue);
 
447
                        if ((r != -1 || errno != ESRCH))
 
448
                                continue;
 
449
                }
 
450
                s->restarts = 0;
 
451
                s->pid = assign_servant(s->devname, servant, NULL);
 
452
        }
 
453
}
 
454
 
 
455
void servants_kill(void)
 
456
{
 
457
        struct servants_list_item *s;
 
458
        union sigval svalue;
 
459
 
 
460
        for (s = servants_leader; s; s = s->next) {
 
461
                if (s->pid != 0)
 
462
                        sigqueue(s->pid, SIGKILL, svalue);
 
463
        }
 
464
}
 
465
 
 
466
int check_timeout_inconsistent(void)
 
467
{
 
468
        int devfd;
 
469
        struct sector_header_s *hdr_cur = 0, *hdr_last = 0;
 
470
        struct servants_list_item* s;
 
471
        int inconsistent = 0;
 
472
 
 
473
        for (s = servants_leader; s; s = s->next) {
 
474
                devfd = open_device(s->devname);
 
475
                if (devfd < 0)
 
476
                        continue;
 
477
                hdr_cur = header_get(devfd);
 
478
                close(devfd);
 
479
                if (!hdr_cur)
 
480
                        continue;
 
481
                if (hdr_last) {
 
482
                        if (hdr_last->timeout_watchdog != hdr_cur->timeout_watchdog
 
483
                            || hdr_last->timeout_allocate != hdr_cur->timeout_allocate
 
484
                            || hdr_last->timeout_loop != hdr_cur->timeout_loop
 
485
                            || hdr_last->timeout_msgwait != hdr_cur->timeout_msgwait)
 
486
                                inconsistent = 1;
 
487
                        free(hdr_last);
 
488
                }
 
489
                hdr_last = hdr_cur;
 
490
        }
 
491
 
 
492
        if (hdr_last) {
 
493
                timeout_watchdog = hdr_last->timeout_watchdog;
 
494
                timeout_allocate = hdr_last->timeout_allocate;
 
495
                timeout_loop = hdr_last->timeout_loop;
 
496
                timeout_msgwait = hdr_last->timeout_msgwait;
 
497
        } else { 
 
498
                cl_log(LOG_ERR, "No devices were available at start-up.");
 
499
                exit(1);
 
500
        }
 
501
 
 
502
        free(hdr_last);
 
503
        return inconsistent;
 
504
}
 
505
 
 
506
inline void cleanup_servant_by_pid(pid_t pid)
 
507
{
 
508
        struct servants_list_item* s;
 
509
 
 
510
        s = lookup_servant_by_pid(pid);
 
511
        if (s) {
 
512
                s->pid = 0;
 
513
        } else {
 
514
                /* TODO: This points to an inconsistency in our internal
 
515
                 * data - how to recover? */
 
516
                cl_log(LOG_ERR, "Cannot cleanup after unknown pid %i",
 
517
                                pid);
 
518
        }
 
519
}
 
520
 
 
521
void restart_servant_by_pid(pid_t pid)
 
522
{
 
523
        struct servants_list_item* s;
 
524
 
 
525
        s = lookup_servant_by_pid(pid);
 
526
        if (s) {
 
527
                if (s->restarts < 10) {
 
528
                        s->pid = assign_servant(s->devname, servant, NULL);
 
529
                        s->restarts++;
 
530
                } else {
 
531
                        cl_log(LOG_WARNING, "Max retry count reached: not restarting servant for %s",
 
532
                                        s->devname);
 
533
                }
 
534
 
 
535
        } else {
 
536
                /* TODO: This points to an inconsistency in our internal
 
537
                 * data - how to recover? */
 
538
                cl_log(LOG_ERR, "Cannot restart unknown pid %i",
 
539
                                pid);
 
540
        }
 
541
}
 
542
 
 
543
int inquisitor_decouple(void)
 
544
{
 
545
        pid_t ppid = getppid();
 
546
        union sigval signal_value;
 
547
 
 
548
        /* During start-up, we only arm the watchdog once we've got
 
549
         * quorum at least once. */
 
550
        if (watchdog_use) {
 
551
                if (watchdog_init() < 0) {
 
552
                        return -1;
 
553
                }
 
554
        }
 
555
 
 
556
        if (ppid > 1) {
 
557
                sigqueue(ppid, SIG_LIVENESS, signal_value);
 
558
        }
 
559
        return 0;
 
560
}
 
561
 
 
562
void inquisitor_child(void)
 
563
{
 
564
        int sig, pid, i;
 
565
        sigset_t procmask;
 
566
        siginfo_t sinfo;
 
567
        int *reports;
 
568
        int status;
 
569
        struct timespec timeout;
 
570
        int good_servants = 0;
 
571
        int exiting = 0;
 
572
        int decoupled = 0;
 
573
        time_t latency;
 
574
        struct timespec t_last_tickle, t_now, t_last_restarted;
 
575
 
 
576
        set_proc_title("sbd: inquisitor");
 
577
 
 
578
        reports = malloc(sizeof(int) * servant_count);
 
579
        if (!reports) {
 
580
                cl_log(LOG_ERR, "malloc failed");
 
581
                exit(1);
 
582
        }
 
583
        memset(reports, 0, sizeof(int) * servant_count);
 
584
 
 
585
        sigemptyset(&procmask);
 
586
        sigaddset(&procmask, SIGCHLD);
 
587
        sigaddset(&procmask, SIG_LIVENESS);
 
588
        sigaddset(&procmask, SIG_EXITREQ);
 
589
        sigaddset(&procmask, SIG_TEST);
 
590
        sigaddset(&procmask, SIGUSR1);
 
591
        sigaddset(&procmask, SIGUSR2);
 
592
        sigprocmask(SIG_BLOCK, &procmask, NULL);
 
593
 
 
594
        servants_start();
 
595
 
 
596
        timeout.tv_sec = timeout_loop;
 
597
        timeout.tv_nsec = 0;
 
598
        good_servants = 0;
 
599
        clock_gettime(CLOCK_MONOTONIC, &t_last_tickle);
 
600
        clock_gettime(CLOCK_MONOTONIC, &t_last_restarted);
 
601
 
 
602
        while (1) {
 
603
                sig = sigtimedwait(&procmask, &sinfo, &timeout);
 
604
                DBGPRINT("got signal %d\n", sig);
 
605
 
 
606
                if (sig == SIG_EXITREQ) {
 
607
                        servants_kill();
 
608
                        watchdog_close();
 
609
                        exiting = 1;
 
610
                } else if (sig == SIGCHLD) {
 
611
                        while ((pid = waitpid(-1, &status, WNOHANG))) {
 
612
                                if (pid == -1 && errno == ECHILD) {
 
613
                                        break;
 
614
                                } else if (exiting) {
 
615
                                        cleanup_servant_by_pid(pid);
 
616
                                } else {
 
617
                                        restart_servant_by_pid(pid);
 
618
                                }
 
619
                        }
 
620
                } else if (sig == SIG_LIVENESS) {
 
621
                        for (i = 0; i < servant_count; i++) {
 
622
                                if (reports[i] == sinfo.si_pid) {
 
623
                                        break;
 
624
                                } else if (reports[i] == 0) {
 
625
                                        reports[i] = sinfo.si_pid;
 
626
                                        good_servants++;
 
627
                                        break;
 
628
                                }
 
629
                        }
 
630
                } else if (sig == SIG_TEST) {
 
631
                } else if (sig == SIGUSR1) {
 
632
                        if (exiting)
 
633
                                continue;
 
634
                        clock_gettime(CLOCK_MONOTONIC, &t_last_restarted);
 
635
                        servants_start();
 
636
                }
 
637
 
 
638
                if (exiting) {
 
639
                        if (check_all_dead())
 
640
                                exit(0);
 
641
                        else
 
642
                                continue;
 
643
                }
 
644
 
 
645
                if (quorum_read(good_servants)) {
 
646
                        DBGPRINT("Enough liveness messages\n");
 
647
                        if (!decoupled) {
 
648
                                if (inquisitor_decouple() < 0) {
 
649
                                        servants_kill();
 
650
                                        exiting = 1;
 
651
                                        continue;
 
652
                                } else {
 
653
                                        decoupled = 1;
 
654
                                }
 
655
                        }
 
656
 
 
657
                        watchdog_tickle();
 
658
                        clock_gettime(CLOCK_MONOTONIC, &t_last_tickle);
 
659
                        memset(reports, 0, sizeof(int) * servant_count);
 
660
                        good_servants = 0;
 
661
                }
 
662
 
 
663
                clock_gettime(CLOCK_MONOTONIC, &t_now);
 
664
                latency = t_now.tv_sec - t_last_tickle.tv_sec;
 
665
                if (timeout_watchdog && (latency > timeout_watchdog)) {
 
666
                        if (!decoupled) {
 
667
                                /* We're still being watched by our
 
668
                                 * parent. We don't fence, but exit. */
 
669
                                cl_log(LOG_ERR, "SBD: Not enough votes to proceed. Aborting start-up.");
 
670
                                servants_kill();
 
671
                                exiting = 1;
 
672
                                continue;
 
673
                        }
 
674
                        do_reset();
 
675
                }
 
676
                if (timeout_watchdog_warn && (latency > timeout_watchdog_warn)) {
 
677
                        cl_log(LOG_WARNING,
 
678
                               "Latency: No liveness for %d s exceeds threshold of %d s (healthy servants: %d)",
 
679
                               (int)latency, (int)timeout_watchdog_warn, good_servants);
 
680
                }
 
681
                
 
682
                latency = t_now.tv_sec - t_last_restarted.tv_sec;
 
683
                if (servant_restart_interval > 0 
 
684
                                && latency > servant_restart_interval) {
 
685
                        /* Restart all children every hour */
 
686
                        clock_gettime(CLOCK_MONOTONIC, &t_last_restarted);
 
687
                        servants_start();
 
688
                }
 
689
        }
 
690
        /* not reached */
 
691
        exit(0);
 
692
}
 
693
 
 
694
int inquisitor(void)
 
695
{
 
696
        int sig, pid, inquisitor_pid;
 
697
        int status;
 
698
        sigset_t procmask;
 
699
        siginfo_t sinfo;
 
700
 
 
701
        DBGPRINT("inquisitor starting\n");
 
702
 
 
703
        /* Where's the best place for sysrq init ?*/
 
704
        sysrq_init();
 
705
 
 
706
        sigemptyset(&procmask);
 
707
        sigaddset(&procmask, SIGCHLD);
 
708
        sigaddset(&procmask, SIG_LIVENESS);
 
709
        sigprocmask(SIG_BLOCK, &procmask, NULL);
 
710
 
 
711
        if (check_timeout_inconsistent() == 1) {
 
712
                fprintf(stderr, "Timeout settings are different across SBD devices!\n");
 
713
                fprintf(stderr, "You have to correct them and re-start SBD again.\n");
 
714
                return -1;
 
715
        }
 
716
 
 
717
        inquisitor_pid = make_daemon();
 
718
        if (inquisitor_pid == 0) {
 
719
                inquisitor_child();
 
720
        } 
 
721
        
 
722
        /* We're the parent. Wait for a happy signal from our child
 
723
         * before we proceed - we either get "SIG_LIVENESS" when the
 
724
         * inquisitor has completed the first successful round, or
 
725
         * ECHLD when it exits with an error. */
 
726
 
 
727
        while (1) {
 
728
                sig = sigwaitinfo(&procmask, &sinfo);
 
729
                DBGPRINT("get signal %d\n", sig);
 
730
                if (sig == SIGCHLD) {
 
731
                        while ((pid = waitpid(-1, &status, WNOHANG))) {
 
732
                                if (pid == -1 && errno == ECHILD) {
 
733
                                        break;
 
734
                                }
 
735
                                /* We got here because the inquisitor
 
736
                                 * did not succeed. */
 
737
                                return -1;
 
738
                        }
 
739
                } else if (sig == SIG_LIVENESS) {
 
740
                        /* Inquisitor started up properly. */
 
741
                        return 0;
 
742
                } else {
 
743
                        fprintf(stderr, "Nobody expected the spanish inquisition!\n");
 
744
                        continue;
 
745
                }
 
746
        }
 
747
        /* not reached */
 
748
        return -1;
 
749
}
 
750
 
 
751
int messenger(const char *name, const char *msg)
 
752
{
 
753
        int sig = 0;
 
754
        pid_t pid = 0;
 
755
        int status = 0;
 
756
        int servants_finished = 0;
 
757
        int successful_delivery = 0;
 
758
        sigset_t procmask;
 
759
        siginfo_t sinfo;
 
760
        struct servants_list_item *s;
 
761
        struct slot_msg_arg_t slot_msg_arg = {name, msg};
 
762
 
 
763
        sigemptyset(&procmask);
 
764
        sigaddset(&procmask, SIGCHLD);
 
765
        sigprocmask(SIG_BLOCK, &procmask, NULL);
 
766
 
 
767
        for (s = servants_leader; s; s = s->next) {
 
768
                s->pid = assign_servant(s->devname, &slot_msg_wrapper, &slot_msg_arg);
 
769
        }
 
770
        
 
771
        while (!(quorum_write(successful_delivery) || 
 
772
                (servants_finished == servant_count))) {
 
773
                sig = sigwaitinfo(&procmask, &sinfo);
 
774
                DBGPRINT("get signal %d\n", sig);
 
775
                if (sig == SIGCHLD) {
 
776
                        while ((pid = waitpid(-1, &status, WNOHANG))) {
 
777
                                if (pid == -1 && errno == ECHILD) {
 
778
                                        break;
 
779
                                } else {
 
780
                                        DBGPRINT("process %d finished\n", pid);
 
781
                                        servants_finished++;
 
782
                                        if (WIFEXITED(status)
 
783
                                                && WEXITSTATUS(status) == 0) {
 
784
                                                DBGPRINT("exit with %d\n",
 
785
                                                                WEXITSTATUS(status));
 
786
                                                successful_delivery++;
 
787
                                        }
 
788
                                }
 
789
                        }
 
790
                }
 
791
                DBGPRINT("signal %d handled\n", sig);
 
792
        }
 
793
        if (quorum_write(successful_delivery)) {
 
794
                return 0;
 
795
        } else {
 
796
                fprintf(stderr, "Message is not delivered via more then a half of devices\n");
 
797
                return -1;
 
798
        }
 
799
}
 
800
 
 
801
int dump_headers(void)
 
802
{
 
803
        int rc = 0;
 
804
        struct servants_list_item *s = servants_leader;
 
805
        int devfd;
 
806
 
 
807
        for (s = servants_leader; s; s = s->next) {
 
808
                fprintf(stdout, "==Dumping header on disk %s\n", s->devname);
 
809
                devfd = open_device(s->devname);
 
810
                if (devfd == -1)
 
811
                        return -1;
 
812
                rc = header_dump(devfd);
 
813
                close(devfd);
 
814
                if (rc == -1)
 
815
                        return rc;
 
816
                fprintf(stdout, "==Header on disk %s is dumped\n", s->devname);
 
817
        }
 
818
        return rc;
 
819
}
 
820
 
 
821
int main(int argc, char **argv, char **envp)
 
822
{
 
823
        int exit_status = 0;
 
824
        int c;
 
825
 
 
826
        if ((cmdname = strrchr(argv[0], '/')) == NULL) {
 
827
                cmdname = argv[0];
 
828
        } else {
 
829
                ++cmdname;
 
830
        }
 
831
 
 
832
        cl_log_set_entity(cmdname);
 
833
        cl_log_enable_stderr(0);
 
834
        cl_log_set_facility(LOG_DAEMON);
 
835
 
 
836
        get_uname();
 
837
 
 
838
        while ((c = getopt(argc, argv, "DRWhvw:d:n:1:2:3:4:5:t:")) != -1) {
 
839
                switch (c) {
 
840
                case 'D':
 
841
                        /* Ignore for historical reasons */
 
842
                        break;
 
843
                case 'R':
 
844
                        skip_rt = 1;
 
845
                        break;
 
846
                case 'v':
 
847
                        debug = 1;
 
848
                        break;
 
849
                case 'T':
 
850
                        watchdog_set_timeout = 0;
 
851
                        break;
 
852
                case 'W':
 
853
                        watchdog_use = 1;
 
854
                        break;
 
855
                case 'w':
 
856
                        watchdogdev = optarg;
 
857
                        break;
 
858
                case 'd':
 
859
                        recruit_servant(optarg, 0);
 
860
                        break;
 
861
                case 'n':
 
862
                        local_uname = optarg;
 
863
                        break;
 
864
                case '1':
 
865
                        timeout_watchdog = atoi(optarg);
 
866
                        break;
 
867
                case '2':
 
868
                        timeout_allocate = atoi(optarg);
 
869
                        break;
 
870
                case '3':
 
871
                        timeout_loop = atoi(optarg);
 
872
                        break;
 
873
                case '4':
 
874
                        timeout_msgwait = atoi(optarg);
 
875
                        break;
 
876
                case '5':
 
877
                        timeout_watchdog_warn = atoi(optarg);
 
878
                        break;
 
879
                case 't':
 
880
                        servant_restart_interval = atoi(optarg);
 
881
                        break;
 
882
                case 'h':
 
883
                        usage();
 
884
                        return (0);
 
885
                default:
 
886
                        exit_status = -1;
 
887
                        goto out;
 
888
                        break;
 
889
                }
 
890
        }
 
891
        
 
892
        if (servant_count < 1 || servant_count > 3) {
 
893
                fprintf(stderr, "You must specify 1 to 3 devices via the -d option.\n");
 
894
                exit_status = -1;
 
895
                goto out;
 
896
        }
 
897
 
 
898
        /* There must at least be one command following the options: */
 
899
        if ((argc - optind) < 1) {
 
900
                fprintf(stderr, "Not enough arguments.\n");
 
901
                exit_status = -1;
 
902
                goto out;
 
903
        }
 
904
 
 
905
        if (init_set_proc_title(argc, argv, envp) < 0) {
 
906
                fprintf(stderr, "Allocation of proc title failed.");
 
907
                exit(1);
 
908
        }
 
909
 
 
910
        maximize_priority();
 
911
 
 
912
        if (strcmp(argv[optind], "create") == 0) {
 
913
                exit_status = init_devices();
 
914
        } else if (strcmp(argv[optind], "dump") == 0) {
 
915
                exit_status = dump_headers();
 
916
        } else if (strcmp(argv[optind], "allocate") == 0) {
 
917
                exit_status = allocate_slots(argv[optind + 1]);
 
918
        } else if (strcmp(argv[optind], "list") == 0) {
 
919
                exit_status = list_slots();
 
920
        } else if (strcmp(argv[optind], "message") == 0) {
 
921
                exit_status = messenger(argv[optind + 1], argv[optind + 2]);
 
922
        } else if (strcmp(argv[optind], "ping") == 0) {
 
923
                exit_status = ping_via_slots(argv[optind + 1]);
 
924
        } else if (strcmp(argv[optind], "watch") == 0) {
 
925
                exit_status = inquisitor();
 
926
        } else {
 
927
                exit_status = -1;
 
928
        }
 
929
 
 
930
out:
 
931
        if (exit_status < 0) {
 
932
                usage();
 
933
                return (1);
 
934
        }
 
935
        return (0);
 
936
}