]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/stored.c
I finally found and squashed the elusive SD crash.
[bacula/bacula] / bacula / src / stored / stored.c
1 /*
2  * Second generation Storage daemon.
3  *
4  * It accepts a number of simple commands from the File daemon
5  * and acts on them. When a request to append data is made,
6  * it opens a data channel and accepts data from the
7  * File daemon.
8  *
9  *   Version $Id$
10  *
11  */
12 /*
13    Copyright (C) 2000-2005 Kern Sibbald
14
15    This program is free software; you can redistribute it and/or
16    modify it under the terms of the GNU General Public License
17    version 2 as amended with additional clauses defined in the
18    file LICENSE in the main source directory.
19
20    This program is distributed in the hope that it will be useful,
21    but WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
23    the file LICENSE for additional details.
24
25  */
26
27 #include "bacula.h"
28 #include "stored.h"
29
30 /* Imported functions */
31
32
33 /* Forward referenced functions */
34 void terminate_stored(int sig);
35 static int check_resources();
36
37 extern "C" void *device_initialization(void *arg);
38
39 #define CONFIG_FILE "bacula-sd.conf"  /* Default config file */
40
41 /* Global variables exported */
42 char OK_msg[]   = "3000 OK\n";
43 char TERM_msg[] = "3999 Terminate\n";
44 STORES *me = NULL;                    /* our Global resource */
45 bool forge_on = false;                /* proceed inspite of I/O errors */
46 pthread_mutex_t device_release_mutex = PTHREAD_MUTEX_INITIALIZER;
47 pthread_cond_t wait_device_release = PTHREAD_COND_INITIALIZER;
48
49
50 static uint32_t VolSessionId = 0;
51 uint32_t VolSessionTime;
52 char *configfile = NULL;
53 bool init_done = false;
54
55 /* Global static variables */
56 static int foreground = 0;
57 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
58 static workq_t dird_workq;            /* queue for processing connections */
59
60
61 static void usage()
62 {
63    fprintf(stderr, _(
64 "Copyright (C) 2000-2005 Kern Sibbald.\n"
65 "\nVersion: " VERSION " (" BDATE ")\n\n"
66 "Usage: stored [options] [-c config_file] [config_file]\n"
67 "        -c <file>   use <file> as configuration file\n"
68 "        -dnn        set debug level to nn\n"
69 "        -f          run in foreground (for debugging)\n"
70 "        -g <group>  set groupid to group\n"
71 "        -p          proceed despite I/O errors\n"
72 "        -s          no signals (for debugging)\n"
73 "        -t          test - read config and exit\n"
74 "        -u <user>   userid to <user>\n"
75 "        -v          verbose user messages\n"
76 "        -?          print this message.\n"
77 "\n"));
78    exit(1);
79 }
80
81 /*********************************************************************
82  *
83  *  Main Bacula Unix Storage Daemon
84  *
85  */
86 int main (int argc, char *argv[])
87 {
88    int ch;
89    int no_signals = FALSE;
90    int test_config = FALSE;
91    pthread_t thid;
92    char *uid = NULL;
93    char *gid = NULL;
94
95    init_stack_dump();
96    my_name_is(argc, argv, "bacula-sd");
97    textdomain("bacula");
98    init_msg(NULL, NULL);
99    daemon_start_time = time(NULL);
100
101    /* Sanity checks */
102    if (TAPE_BSIZE % B_DEV_BSIZE != 0 || TAPE_BSIZE / B_DEV_BSIZE == 0) {
103       Emsg2(M_ABORT, 0, "Tape block size (%d) not multiple of system size (%d)\n",
104          TAPE_BSIZE, B_DEV_BSIZE);
105    }
106    if (TAPE_BSIZE != (1 << (ffs(TAPE_BSIZE)-1))) {
107       Emsg1(M_ABORT, 0, "Tape block size (%d) is not a power of 2\n", TAPE_BSIZE);
108    }
109
110    while ((ch = getopt(argc, argv, "c:d:fg:pstu:v?")) != -1) {
111       switch (ch) {
112       case 'c':                    /* configuration file */
113          if (configfile != NULL) {
114             free(configfile);
115          }
116          configfile = bstrdup(optarg);
117          break;
118
119       case 'd':                    /* debug level */
120          debug_level = atoi(optarg);
121          if (debug_level <= 0) {
122             debug_level = 1;
123          }
124          break;
125
126       case 'f':                    /* run in foreground */
127          foreground = TRUE;
128          break;
129
130       case 'g':                    /* set group id */
131          gid = optarg;
132          break;
133
134       case 'p':                    /* proceed in spite of I/O errors */
135          forge_on = true;
136          break;
137
138       case 's':                    /* no signals */
139          no_signals = TRUE;
140          break;
141
142       case 't':
143          test_config = TRUE;
144          break;
145
146       case 'u':                    /* set uid */
147          uid = optarg;
148          break;
149
150       case 'v':                    /* verbose */
151          verbose++;
152          break;
153
154       case '?':
155       default:
156          usage();
157          break;
158       }
159    }
160    argc -= optind;
161    argv += optind;
162
163    if (argc) {
164       if (configfile != NULL) {
165          free(configfile);
166       }
167       configfile = bstrdup(*argv);
168       argc--;
169       argv++;
170    }
171    if (argc)
172       usage();
173
174    if (!no_signals) {
175       init_signals(terminate_stored);
176    }
177
178    if (configfile == NULL) {
179       configfile = bstrdup(CONFIG_FILE);
180    }
181
182    parse_config(configfile);
183
184    if (init_tls() != 0) {
185       Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("TLS library initialization failed.\n"));
186    }
187
188    if (!check_resources()) {
189       Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile);
190    }
191
192    if (test_config) {
193       terminate_stored(0);
194    }
195
196    my_name_is(0, (char **)NULL, me->hdr.name);     /* Set our real name */
197
198    if (!foreground) {
199       daemon_start();                 /* become daemon */
200       init_stack_dump();              /* pick up new pid */
201    }
202
203    create_pid_file(me->pid_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
204    read_state_file(me->working_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
205
206    drop(uid, gid);
207
208    /* Ensure that Volume Session Time and Id are both
209     * set and are both non-zero.
210     */
211    VolSessionTime = (long)daemon_start_time;
212    if (VolSessionTime == 0) { /* paranoid */
213       Jmsg0(NULL, M_ABORT, 0, _("Volume Session Time is ZERO!\n"));
214    }
215
216    init_python_interpreter(me->hdr.name, me->scripts_directory, "SDStartUp");
217
218    /* Make sure on Solaris we can run concurrent, watch dog + servers + misc */
219    set_thread_concurrency(me->max_concurrent_jobs * 2 + 4);
220
221     /*
222      * Start the device allocation thread
223      */
224    create_volume_list();              /* do before device_init */
225    if (pthread_create(&thid, NULL, device_initialization, NULL) != 0) {
226       Emsg1(M_ABORT, 0, _("Unable to create thread. ERR=%s\n"), strerror(errno));
227    }
228
229    start_watchdog();                  /* start watchdog thread */
230    init_jcr_subsystem();              /* start JCR watchdogs etc. */
231
232    /* Single server used for Director and File daemon */
233    bnet_thread_server(me->sdaddrs, me->max_concurrent_jobs * 2 + 1,
234                       &dird_workq, handle_connection_request);
235    exit(1);                           /* to keep compiler quiet */
236 }
237
238 /* Return a new Session Id */
239 uint32_t newVolSessionId()
240 {
241    uint32_t Id;
242
243    P(mutex);
244    VolSessionId++;
245    Id = VolSessionId;
246    V(mutex);
247    return Id;
248 }
249
250 /* Check Configuration file for necessary info */
251 static int check_resources()
252 {
253    bool OK = true;
254    AUTOCHANGER *changer;
255
256
257    me = (STORES *)GetNextRes(R_STORAGE, NULL);
258    if (!me) {
259       Jmsg1(NULL, M_ERROR, 0, _("No Storage resource defined in %s. Cannot continue.\n"),
260          configfile);
261       OK = false;
262    }
263
264    if (GetNextRes(R_STORAGE, (RES *)me) != NULL) {
265       Jmsg1(NULL, M_ERROR, 0, _("Only one Storage resource permitted in %s\n"),
266          configfile);
267       OK = false;
268    }
269    if (GetNextRes(R_DIRECTOR, NULL) == NULL) {
270       Jmsg1(NULL, M_ERROR, 0, _("No Director resource defined in %s. Cannot continue.\n"),
271          configfile);
272       OK = false;
273    }
274    if (GetNextRes(R_DEVICE, NULL) == NULL){
275       Jmsg1(NULL, M_ERROR, 0, _("No Device resource defined in %s. Cannot continue.\n"),
276            configfile);
277       OK = false;
278    }
279
280    if (!me->messages) {
281       me->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
282       if (!me->messages) {
283          Jmsg1(NULL, M_ERROR, 0, _("No Messages resource defined in %s. Cannot continue.\n"),
284             configfile);
285          OK = false;
286       }
287    }
288
289    if (!me->working_directory) {
290       Jmsg1(NULL, M_ERROR, 0, _("No Working Directory defined in %s. Cannot continue.\n"),
291          configfile);
292       OK = false;
293    }
294
295    DIRRES *director;
296    STORES *store;
297    foreach_res(store, R_STORAGE) { 
298       /* tls_require implies tls_enable */
299       if (store->tls_require) {
300          if (have_tls) {
301             store->tls_enable = true;
302          } else {
303             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
304             OK = false;
305             continue;
306          }
307       }
308
309       if (!store->tls_certfile && store->tls_enable) {
310          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Storage \"%s\" in %s.\n"),
311               store->hdr.name, configfile);
312          OK = false;
313       }
314
315       if (!store->tls_keyfile && store->tls_enable) {
316          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Storage \"%s\" in %s.\n"),
317               store->hdr.name, configfile);
318          OK = false;
319       }
320
321       if ((!store->tls_ca_certfile && !store->tls_ca_certdir) && store->tls_enable && store->tls_verify_peer) {
322          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
323               " or \"TLS CA Certificate Dir\" are defined for Storage \"%s\" in %s."
324               " At least one CA certificate store is required"
325               " when using \"TLS Verify Peer\".\n"),
326               store->hdr.name, configfile);
327          OK = false;
328       }
329
330       /* If everything is well, attempt to initialize our per-resource TLS context */
331       if (OK && (store->tls_enable || store->tls_require)) {
332          /* Initialize TLS context:
333           * Args: CA certfile, CA certdir, Certfile, Keyfile,
334           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
335          store->tls_ctx = new_tls_context(store->tls_ca_certfile,
336             store->tls_ca_certdir, store->tls_certfile,
337             store->tls_keyfile, NULL, NULL, store->tls_dhfile,
338             store->tls_verify_peer);
339
340          if (!store->tls_ctx) { 
341             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Storage \"%s\" in %s.\n"),
342                  store->hdr.name, configfile);
343             OK = false;
344          }
345       }
346    }
347
348    foreach_res(director, R_DIRECTOR) { 
349       /* tls_require implies tls_enable */
350       if (director->tls_require) {
351          director->tls_enable = true;
352       }
353
354       if (!director->tls_certfile && director->tls_enable) {
355          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Director \"%s\" in %s.\n"),
356               director->hdr.name, configfile);
357          OK = false;
358       }
359
360       if (!director->tls_keyfile && director->tls_enable) {
361          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Director \"%s\" in %s.\n"),
362               director->hdr.name, configfile);
363          OK = false;
364       }
365
366       if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && director->tls_enable && director->tls_verify_peer) {
367          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
368               " or \"TLS CA Certificate Dir\" are defined for Director \"%s\" in %s."
369               " At least one CA certificate store is required"
370               " when using \"TLS Verify Peer\".\n"),
371               director->hdr.name, configfile);
372          OK = false;
373       }
374
375       /* If everything is well, attempt to initialize our per-resource TLS context */
376       if (OK && (director->tls_enable || director->tls_require)) {
377          /* Initialize TLS context:
378           * Args: CA certfile, CA certdir, Certfile, Keyfile,
379           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
380          director->tls_ctx = new_tls_context(director->tls_ca_certfile,
381             director->tls_ca_certdir, director->tls_certfile,
382             director->tls_keyfile, NULL, NULL, director->tls_dhfile,
383             director->tls_verify_peer);
384
385          if (!director->tls_ctx) { 
386             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"),
387                  director->hdr.name, configfile);
388             OK = false;
389          }
390       }
391    }
392
393    /* Ensure that the media_type for each device is the same */
394    foreach_res(changer, R_AUTOCHANGER) {
395       DEVRES *device;
396       char *media_type = NULL;
397       foreach_alist(device, changer->device) {
398          /*
399           * If the device does not have a changer name or changer command
400           *   defined, used the one from the Autochanger resource 
401           */
402          if (!device->changer_name && changer->changer_name) {
403             device->changer_name = bstrdup(changer->changer_name);
404          }
405          if (!device->changer_command && changer->changer_command) {
406             device->changer_command = bstrdup(changer->changer_command);
407          }
408          if (!device->changer_name) {
409             Jmsg(NULL, M_ERROR, 0, 
410                _("No Changer Name given for device %s. Cannot continue.\n"),
411                device->hdr.name);
412             OK = false;
413          }   
414          if (!device->changer_command) {
415             Jmsg(NULL, M_ERROR, 0, 
416                _("No Changer Command given for device %s. Cannot continue.\n"),
417                device->hdr.name);
418             OK = false;
419          }   
420
421          if (media_type == NULL) {
422             media_type = device->media_type;     /* get Media Type of first device */
423             continue;
424          }     
425          /* Ensure that other devices Media Types are the same */
426          if (strcmp(media_type, device->media_type) != 0) {
427             Jmsg(NULL, M_ERROR, 0, 
428                _("Media Type not the same for all devices in changer %s. Cannot continue.\n"),
429                changer->hdr.name);
430             OK = false;
431             continue;
432          }
433       }
434    }
435    
436    if (OK) {
437       close_msg(NULL);                   /* close temp message handler */
438       init_msg(NULL, me->messages);      /* open daemon message handler */
439       set_working_directory(me->working_directory);
440    }
441
442    return OK;
443 }
444
445 /*
446  * Here we attempt to init and open each device. This is done
447  *  once at startup in a separate thread.
448  */
449 extern "C"
450 void *device_initialization(void *arg)
451 {
452    DEVRES *device;
453    DCR *dcr;
454    JCR *jcr;
455    DEVICE *dev;
456
457    LockRes();
458
459    pthread_detach(pthread_self());
460    jcr = new_jcr(sizeof(JCR), stored_free_jcr);
461    jcr->JobType = JT_SYSTEM;
462    /* Initialize FD start condition variable */
463    int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
464    if (errstat != 0) {
465       Jmsg1(jcr, M_ABORT, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat));
466    }
467
468    foreach_res(device, R_DEVICE) {
469       Dmsg1(90, "calling init_dev %s\n", device->device_name);
470       device->dev = dev = init_dev(NULL, device);
471       Dmsg1(10, "SD init done %s\n", device->device_name);
472       if (!dev) {
473          Jmsg1(NULL, M_ERROR, 0, _("Could not initialize %s\n"), device->device_name);
474          continue;
475       }
476
477       dcr = new_dcr(jcr, dev);
478
479       if (device->cap_bits & CAP_ALWAYSOPEN) {
480          Dmsg1(20, "calling first_open_device %s\n", dev->print_name());
481          if (!first_open_device(dcr)) {
482             Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"), dev->print_name());
483             Dmsg1(20, "Could not open device %s\n", dev->print_name());
484             term_dev(dev);
485             device->dev = NULL;
486             free_dcr(dcr);
487             continue;
488          }
489       }
490       if (device->cap_bits & CAP_AUTOMOUNT && dev->is_open()) {
491          switch (read_dev_volume_label(dcr)) {
492          case VOL_OK:
493             memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
494             break;
495          default:
496             Jmsg1(NULL, M_WARNING, 0, _("Could not mount device %s\n"), dev->print_name());
497             break;
498          }
499       }
500       free_dcr(dcr);
501    }
502    free_jcr(jcr); 
503    init_done = true;
504    UnlockRes();
505    return NULL;
506 }
507
508
509 /* Clean up and then exit */
510 void terminate_stored(int sig)
511 {
512    static bool in_here = false;
513    DEVRES *device;
514    JCR *jcr;
515
516    if (in_here) {                     /* prevent loops */
517       exit(1);
518    }
519    in_here = true;
520
521    if (sig == SIGTERM) {              /* normal shutdown request? */
522       /*
523        * This is a normal shutdown request. We wiffle through
524        *   all open jobs canceling them and trying to wake
525        *   them up so that they will report back the correct
526        *   volume status.
527        */
528       foreach_jcr(jcr) {
529          BSOCK *fd;
530          if (jcr->JobId == 0) {
531             free_jcr(jcr);
532             continue;                 /* ignore console */
533          }
534          set_jcr_job_status(jcr, JS_Canceled);
535          fd = jcr->file_bsock;
536          if (fd) {
537             fd->timed_out = true;
538             Dmsg1(100, "term_stored killing JobId=%d\n", jcr->JobId);
539             pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
540             /* ***FIXME*** wiffle through all dcrs */
541             if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->dev_blocked) {
542                pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol);
543                pthread_cond_broadcast(&wait_device_release);
544             }
545             bmicrosleep(0, 50000);
546          }
547          free_jcr(jcr);
548       }
549       bmicrosleep(0, 500000);         /* give them 1/2 sec to clean up */
550    }
551
552    write_state_file(me->working_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
553    delete_pid_file(me->pid_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
554
555    Dmsg1(200, "In terminate_stored() sig=%d\n", sig);
556
557    foreach_res(device, R_DEVICE) {
558       Dmsg1(10, "Term device %s\n", device->device_name);
559       if (device->dev) {
560          free_volume(device->dev);
561          term_dev(device->dev);
562       } else {
563          Dmsg1(10, "No dev structure %s\n", device->device_name);
564       }
565    }
566
567    if (configfile) {
568       free(configfile);
569       configfile = NULL;
570    }
571    free_config_resources();
572
573    if (debug_level > 10) {
574       print_memory_pool_stats();
575    }
576    term_msg();
577    stop_watchdog();
578    cleanup_tls();
579    free_volume_list();
580    close_memory_pool();
581
582    sm_dump(false);                    /* dump orphaned buffers */
583    exit(sig);
584 }