2 * Second generation Storage daemon.
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
13 Copyright (C) 2000-2005 Kern Sibbald
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 ammended with additional clauses defined in the
18 file LICENSE in the main source directory.
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.
30 /* Imported functions */
33 /* Forward referenced functions */
34 void terminate_stored(int sig);
35 static int check_resources();
37 extern "C" void *device_initialization(void *arg);
39 #define CONFIG_FILE "bacula-sd.conf" /* Default config file */
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;
50 static uint32_t VolSessionId = 0;
51 uint32_t VolSessionTime;
52 char *configfile = NULL;
54 /* Global static variables */
55 static int foreground = 0;
56 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
57 static workq_t dird_workq; /* queue for processing connections */
63 "Copyright (C) 2000-2005 Kern Sibbald.\n"
64 "\nVersion: " VERSION " (" BDATE ")\n\n"
65 "Usage: stored [options] [-c config_file] [config_file]\n"
66 " -c <file> use <file> as configuration file\n"
67 " -dnn set debug level to nn\n"
68 " -f run in foreground (for debugging)\n"
69 " -g <group> set groupid to group\n"
70 " -p proceed despite I/O errors\n"
71 " -s no signals (for debugging)\n"
72 " -t test - read config and exit\n"
73 " -u <user> userid to <user>\n"
74 " -v verbose user messages\n"
75 " -? print this message.\n"
80 /*********************************************************************
82 * Main Bacula Unix Storage Daemon
85 int main (int argc, char *argv[])
88 int no_signals = FALSE;
89 int test_config = FALSE;
95 my_name_is(argc, argv, "bacula-sd");
98 daemon_start_time = time(NULL);
101 if (TAPE_BSIZE % B_DEV_BSIZE != 0 || TAPE_BSIZE / B_DEV_BSIZE == 0) {
102 Emsg2(M_ABORT, 0, "Tape block size (%d) not multiple of system size (%d)\n",
103 TAPE_BSIZE, B_DEV_BSIZE);
105 if (TAPE_BSIZE != (1 << (ffs(TAPE_BSIZE)-1))) {
106 Emsg1(M_ABORT, 0, "Tape block size (%d) is not a power of 2\n", TAPE_BSIZE);
109 while ((ch = getopt(argc, argv, "c:d:fg:pstu:v?")) != -1) {
111 case 'c': /* configuration file */
112 if (configfile != NULL) {
115 configfile = bstrdup(optarg);
118 case 'd': /* debug level */
119 debug_level = atoi(optarg);
120 if (debug_level <= 0) {
125 case 'f': /* run in foreground */
129 case 'g': /* set group id */
133 case 'p': /* proceed in spite of I/O errors */
137 case 's': /* no signals */
145 case 'u': /* set uid */
149 case 'v': /* verbose */
163 if (configfile != NULL) {
166 configfile = bstrdup(*argv);
174 init_signals(terminate_stored);
177 if (configfile == NULL) {
178 configfile = bstrdup(CONFIG_FILE);
181 parse_config(configfile);
183 if (init_tls() != 0) {
184 Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("TLS library initialization failed.\n"));
187 if (!check_resources()) {
188 Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile);
195 my_name_is(0, (char **)NULL, me->hdr.name); /* Set our real name */
198 daemon_start(); /* become daemon */
199 init_stack_dump(); /* pick up new pid */
202 create_pid_file(me->pid_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
203 read_state_file(me->working_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
207 /* Ensure that Volume Session Time and Id are both
208 * set and are both non-zero.
210 VolSessionTime = (long)daemon_start_time;
211 if (VolSessionTime == 0) { /* paranoid */
212 Jmsg0(NULL, M_ABORT, 0, _("Volume Session Time is ZERO!\n"));
215 init_python_interpreter(me->hdr.name, me->scripts_directory, "SDStartUp");
217 /* Make sure on Solaris we can run concurrent, watch dog + servers + misc */
218 set_thread_concurrency(me->max_concurrent_jobs * 2 + 4);
221 * Start the device allocation thread
223 if (pthread_create(&thid, NULL, device_initialization, NULL) != 0) {
224 Emsg1(M_ABORT, 0, _("Unable to create thread. ERR=%s\n"), strerror(errno));
227 start_watchdog(); /* start watchdog thread */
229 init_jcr_subsystem(); /* start JCR watchdogs etc. */
232 * Sleep a bit to give device thread a chance to lock the resource
233 * chain before we start the server.
237 /* Wait for device initialization to complete */
241 /* Single server used for Director and File daemon */
242 bnet_thread_server(me->sdaddrs, me->max_concurrent_jobs * 2 + 1,
243 &dird_workq, handle_connection_request);
244 exit(1); /* to keep compiler quiet */
247 /* Return a new Session Id */
248 uint32_t newVolSessionId()
259 /* Check Configuration file for necessary info */
260 static int check_resources()
263 AUTOCHANGER *changer;
267 me = (STORES *)GetNextRes(R_STORAGE, NULL);
269 Jmsg1(NULL, M_ERROR, 0, _("No Storage resource defined in %s. Cannot continue.\n"),
274 if (GetNextRes(R_STORAGE, (RES *)me) != NULL) {
275 Jmsg1(NULL, M_ERROR, 0, _("Only one Storage resource permitted in %s\n"),
279 if (GetNextRes(R_DIRECTOR, NULL) == NULL) {
280 Jmsg1(NULL, M_ERROR, 0, _("No Director resource defined in %s. Cannot continue.\n"),
284 if (GetNextRes(R_DEVICE, NULL) == NULL){
285 Jmsg1(NULL, M_ERROR, 0, _("No Device resource defined in %s. Cannot continue.\n"),
291 me->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
293 Jmsg1(NULL, M_ERROR, 0, _("No Messages resource defined in %s. Cannot continue.\n"),
299 if (!me->working_directory) {
300 Jmsg1(NULL, M_ERROR, 0, _("No Working Directory defined in %s. Cannot continue.\n"),
308 foreach_res(store, R_STORAGE) {
309 /* tls_require implies tls_enable */
310 if (store->tls_require) {
311 store->tls_enable = true;
314 if (!store->tls_certfile && store->tls_enable) {
315 Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Storage \"%s\" in %s.\n"),
316 store->hdr.name, configfile);
320 if (!store->tls_keyfile && store->tls_enable) {
321 Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Storage \"%s\" in %s.\n"),
322 store->hdr.name, configfile);
326 if ((!store->tls_ca_certfile && !store->tls_ca_certdir) && store->tls_enable && store->tls_verify_peer) {
327 Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
328 " or \"TLS CA Certificate Dir\" are defined for Storage \"%s\" in %s."
329 " At least one CA certificate store is required"
330 " when using \"TLS Verify Peer\".\n"),
331 store->hdr.name, configfile);
335 /* If everything is well, attempt to initialize our per-resource TLS context */
336 if (OK && (store->tls_enable || store->tls_require)) {
337 /* Initialize TLS context:
338 * Args: CA certfile, CA certdir, Certfile, Keyfile,
339 * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
340 store->tls_ctx = new_tls_context(store->tls_ca_certfile,
341 store->tls_ca_certdir, store->tls_certfile,
342 store->tls_keyfile, NULL, NULL, store->tls_dhfile,
343 store->tls_verify_peer);
345 if (!store->tls_ctx) {
346 Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Storage \"%s\" in %s.\n"),
347 store->hdr.name, configfile);
353 foreach_res(director, R_DIRECTOR) {
354 /* tls_require implies tls_enable */
355 if (director->tls_require) {
356 director->tls_enable = true;
359 if (!director->tls_certfile && director->tls_enable) {
360 Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Director \"%s\" in %s.\n"),
361 director->hdr.name, configfile);
365 if (!director->tls_keyfile && director->tls_enable) {
366 Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Director \"%s\" in %s.\n"),
367 director->hdr.name, configfile);
371 if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && director->tls_enable && director->tls_verify_peer) {
372 Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
373 " or \"TLS CA Certificate Dir\" are defined for Director \"%s\" in %s."
374 " At least one CA certificate store is required"
375 " when using \"TLS Verify Peer\".\n"),
376 director->hdr.name, configfile);
380 /* If everything is well, attempt to initialize our per-resource TLS context */
381 if (OK && (director->tls_enable || director->tls_require)) {
382 /* Initialize TLS context:
383 * Args: CA certfile, CA certdir, Certfile, Keyfile,
384 * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
385 director->tls_ctx = new_tls_context(director->tls_ca_certfile,
386 director->tls_ca_certdir, director->tls_certfile,
387 director->tls_keyfile, NULL, NULL, director->tls_dhfile,
388 director->tls_verify_peer);
390 if (!director->tls_ctx) {
391 Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"),
392 director->hdr.name, configfile);
397 #endif /* HAVE_TLS */
399 /* Ensure that the media_type for each device is the same */
400 foreach_res(changer, R_AUTOCHANGER) {
402 char *media_type = NULL;
403 foreach_alist(device, changer->device) {
405 * If the device does not have a changer name or changer command
406 * defined, used the one from the Autochanger resource
408 if (!device->changer_name && changer->changer_name) {
409 device->changer_name = bstrdup(changer->changer_name);
411 if (!device->changer_command && changer->changer_command) {
412 device->changer_command = bstrdup(changer->changer_command);
414 if (!device->changer_name) {
415 Jmsg(NULL, M_ERROR, 0,
416 _("No Changer Name given for device %s. Cannot continue.\n"),
420 if (!device->changer_command) {
421 Jmsg(NULL, M_ERROR, 0,
422 _("No Changer Command given for device %s. Cannot continue.\n"),
427 if (media_type == NULL) {
428 media_type = device->media_type; /* get Media Type of first device */
431 /* Ensure that other devices Media Types are the same */
432 if (strcmp(media_type, device->media_type) != 0) {
433 Jmsg(NULL, M_ERROR, 0,
434 _("Media Type not the same for all devices in changer %s. Cannot continue.\n"),
443 close_msg(NULL); /* close temp message handler */
444 init_msg(NULL, me->messages); /* open daemon message handler */
445 set_working_directory(me->working_directory);
452 * Here we attempt to init and open each device. This is done
453 * once at startup in a separate thread.
456 void *device_initialization(void *arg)
461 pthread_detach(pthread_self());
463 foreach_res(device, R_DEVICE) {
464 Dmsg1(90, "calling init_dev %s\n", device->device_name);
465 device->dev = init_dev(NULL, NULL, device);
466 Dmsg1(10, "SD init done %s\n", device->device_name);
468 Jmsg1(NULL, M_ERROR, 0, _("Could not initialize %s\n"), device->device_name);
472 if (device->cap_bits & CAP_ALWAYSOPEN) {
473 Dmsg1(20, "calling first_open_device %s\n", device->device_name);
474 if (!first_open_device(device->dev)) {
475 Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"), device->device_name);
478 if (device->cap_bits & CAP_AUTOMOUNT && device->dev &&
479 device->dev->is_open()) {
482 jcr = new_jcr(sizeof(JCR), stored_free_jcr);
483 jcr->JobType = JT_SYSTEM;
484 /* Initialize FD start condition variable */
485 int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
487 Jmsg1(jcr, M_ABORT, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat));
489 dcr = new_dcr(jcr, device->dev);
490 switch (read_dev_volume_label(dcr)) {
492 memcpy(&dcr->dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dcr->dev->VolCatInfo));
495 Jmsg1(NULL, M_WARNING, 0, _("Could not mount device %s\n"), device->device_name);
506 /* Clean up and then exit */
507 void terminate_stored(int sig)
509 static bool in_here = false;
513 if (in_here) { /* prevent loops */
518 if (sig == SIGTERM) { /* normal shutdown request? */
520 * This is a normal shutdown request. We wiffle through
521 * all open jobs canceling them and trying to wake
522 * them up so that they will report back the correct
527 if (jcr->JobId == 0) {
529 continue; /* ignore console */
531 set_jcr_job_status(jcr, JS_Canceled);
532 fd = jcr->file_bsock;
534 fd->timed_out = true;
535 Dmsg1(100, "term_stored killing JobId=%d\n", jcr->JobId);
536 pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
537 /* ***FIXME*** wiffle through all dcrs */
538 if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->dev_blocked) {
539 pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol);
540 pthread_cond_broadcast(&wait_device_release);
542 bmicrosleep(0, 50000);
546 bmicrosleep(0, 500000); /* give them 1/2 sec to clean up */
549 write_state_file(me->working_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
550 delete_pid_file(me->pid_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
552 Dmsg1(200, "In terminate_stored() sig=%d\n", sig);
554 foreach_res(device, R_DEVICE) {
556 term_dev(device->dev);
562 free_config_resources();
564 if (debug_level > 10) {
565 print_memory_pool_stats();
572 sm_dump(false); /* dump orphaned buffers */