2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2017 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Routines for handling the autochanger.
23 * Written by Kern Sibbald, August MMII
26 #include "bacula.h" /* pull in global headers */
27 #include "stored.h" /* pull in Storage Deamon headers */
29 static const int dbglvl = 60;
31 /* Forward referenced functions */
32 static void lock_changer(DCR *dcr);
33 static void unlock_changer(DCR *dcr);
34 static bool unload_other_drive(DCR *dcr, int slot, bool writing);
36 bool DCR::is_virtual_autochanger()
38 return device->changer_command &&
39 (device->changer_command[0] == 0 ||
40 strcmp(device->changer_command, "/dev/null") == 0);
43 /* Init all the autochanger resources found */
44 bool init_autochangers()
48 /* Ensure that the media_type for each device is the same */
49 foreach_res(changer, R_AUTOCHANGER) {
51 foreach_alist(device, changer->device) {
53 * If the device does not have a changer name or changer command
54 * defined, use the one from the Autochanger resource
56 if (!device->changer_name && changer->changer_name) {
57 device->changer_name = bstrdup(changer->changer_name);
59 if (!device->changer_command && changer->changer_command) {
60 device->changer_command = bstrdup(changer->changer_command);
62 if (!device->changer_name) {
63 Jmsg(NULL, M_ERROR, 0,
64 _("No Changer Name given for device %s. Cannot continue.\n"),
68 if (!device->changer_command) {
69 Jmsg(NULL, M_ERROR, 0,
70 _("No Changer Command given for device %s. Cannot continue.\n"),
81 * Called here to do an autoload using the autochanger, if
82 * configured, and if a Slot has been defined for this Volume.
83 * On success this routine loads the indicated tape, but the
84 * label is not read, so it must be verified.
86 * Note if dir is not NULL, it is the console requesting the
87 * autoload for labeling, so we respond directly to the
90 * Returns: 1 on success
91 * 0 on failure (no changer available)
92 * -1 on error on autochanger
94 int autoload_device(DCR *dcr, bool writing, BSOCK *dir)
97 DEVICE * volatile dev = dcr->dev;
98 char *new_vol_name = dcr->VolumeName;
100 int drive = dev->drive_index;
101 int rtn_stat = -1; /* error status */
104 if (!dev->is_autochanger()) {
105 Dmsg1(dbglvl, "Device %s is not an autochanger\n", dev->print_name());
109 /* An empty ChangerCommand => virtual disk autochanger */
110 if (dcr->is_virtual_autochanger()) {
111 Dmsg0(dbglvl, "ChangerCommand=0, virtual disk changer\n");
112 return 1; /* nothing to load */
115 slot = dcr->VolCatInfo.InChanger ? dcr->VolCatInfo.Slot : 0;
117 * Handle autoloaders here. If we cannot autoload it, we
118 * will return 0 so that the sysop will be asked to load it.
120 if (writing && slot <= 0) {
122 return 0; /* For user, bail out right now */
124 /* ***FIXME*** this really should not be here */
125 if (dir_find_next_appendable_volume(dcr)) {
126 slot = dcr->VolCatInfo.InChanger ? dcr->VolCatInfo.Slot : 0;
132 Dmsg4(dbglvl, "Want slot=%d drive=%d InChgr=%d Vol=%s\n",
133 dcr->VolCatInfo.Slot, drive,
134 dcr->VolCatInfo.InChanger, dcr->getVolCatName());
136 changer = get_pool_memory(PM_FNAME);
138 /* Suppress info when polling */
140 Jmsg(jcr, M_INFO, 0, _("No slot defined in catalog (slot=%d) for Volume \"%s\" on %s.\n"),
141 slot, dcr->getVolCatName(), dev->print_name());
142 Jmsg(jcr, M_INFO, 0, _("Cartridge change or \"update slots\" may be required.\n"));
145 } else if (!dcr->device->changer_name) {
146 /* Suppress info when polling */
148 Jmsg(jcr, M_INFO, 0, _("No \"Changer Device\" for %s. Manual load of Volume may be required.\n"),
152 } else if (!dcr->device->changer_command) {
153 /* Suppress info when polling */
155 Jmsg(jcr, M_INFO, 0, _("No \"Changer Command\" for %s. Manual load of Volume may be requird.\n"),
160 /* Attempt to load the Volume */
161 uint32_t timeout = dcr->device->max_changer_wait;
164 loaded = get_autochanger_loaded_slot(dcr);
165 if (loaded < 0) { /* Autochanger error, try again */
166 loaded = get_autochanger_loaded_slot(dcr);
168 Dmsg2(dbglvl, "Found loaded=%d drive=%d\n", loaded, drive);
170 if (loaded <= 0 || loaded != slot) {
171 POOL_MEM results(PM_MESSAGE);
173 /* Unload anything in our drive */
174 if (!unload_autochanger(dcr, loaded)) {
178 /* Make sure desired slot is unloaded */
179 if (!unload_other_drive(dcr, slot, writing)) {
184 * Load the desired cassette
187 Dmsg2(dbglvl, "Doing changer load slot %d %s\n", slot, dev->print_name());
189 _("3304 Issuing autochanger \"load Volume %s, Slot %d, Drive %d\" command.\n"),
190 new_vol_name, slot, drive);
192 "3304 Issuing autochanger \"load Volume %s, Slot %d, Drive %d\" command.\n",
193 new_vol_name, slot, drive);
195 dcr->VolCatInfo.Slot = slot; /* slot to be loaded */
196 changer = edit_device_codes(dcr, changer, dcr->device->changer_command, "load");
198 Dmsg1(dbglvl, "Run program=%s\n", changer);
199 status = run_program_full_output(changer, timeout, results.addr());
201 Jmsg(jcr, M_INFO, 0, _("3305 Autochanger \"load Volume %s, Slot %d, Drive %d\", status is OK.\n"),
202 new_vol_name, slot, drive);
203 Dmsg3(dbglvl, "OK: load volume %s, slot %d, drive %d.\n", new_vol_name, slot, drive);
204 bstrncpy(dev->LoadedVolName, new_vol_name, sizeof(dev->LoadedVolName));
205 dev->set_slot(slot); /* set currently loaded slot */
207 /* We just swapped this Volume so it cannot be swapping any more */
208 dev->vol->clear_swapping();
212 be.set_errno(status);
213 Dmsg5(dbglvl, "Error: load Volume %s, Slot %d, Drive %d, bad stats=%s.\nResults=%s\n",
214 new_vol_name, slot, drive,
215 be.bstrerror(), results.c_str());
216 Jmsg(jcr, M_FATAL, 0, _("3992 Bad autochanger \"load Volume %s Slot %d, Drive %d\": "
217 "ERR=%s.\nResults=%s\n"),
218 new_vol_name, slot, drive, be.bstrerror(), results.c_str());
219 rtn_stat = -1; /* hard error */
220 dev->clear_slot(); /* mark unknown */
224 status = 0; /* we got what we want */
225 dev->set_slot(slot); /* set currently loaded slot */
226 bstrncpy(dev->LoadedVolName, new_vol_name, sizeof(dev->LoadedVolName));
228 Dmsg1(dbglvl, "After changer, status=%d\n", status);
229 if (status == 0) { /* did we succeed? */
230 rtn_stat = 1; /* tape loaded by changer */
233 free_pool_memory(changer);
237 free_pool_memory(changer);
243 * Returns: -1 if error from changer command
245 * Note, this is safe to do without releasing the drive
246 * since it does not attempt load/unload a slot.
248 int get_autochanger_loaded_slot(DCR *dcr)
251 DEVICE *dev = dcr->dev;
253 uint32_t timeout = dcr->device->max_changer_wait;
254 int drive = dcr->dev->drive_index;
255 POOL_MEM results(PM_MESSAGE);
258 if (!dev->is_autochanger()) {
261 if (!dcr->device->changer_command) {
265 if (dev->get_slot() > 0 && dev->has_cap(CAP_ALWAYSOPEN)) {
266 Dmsg1(dbglvl, "Return cached slot=%d\n", dev->get_slot());
267 return dev->get_slot();
270 /* Virtual disk autochanger */
271 if (dcr->is_virtual_autochanger()) {
275 /* Find out what is loaded, zero means device is unloaded */
276 changer = get_pool_memory(PM_FNAME);
278 /* Suppress info when polling */
279 if (!dev->poll && chk_dbglvl(1)) {
280 Jmsg(jcr, M_INFO, 0, _("3301 Issuing autochanger \"loaded? drive %d\" command.\n"),
283 changer = edit_device_codes(dcr, changer, dcr->device->changer_command, "loaded");
284 Dmsg1(dbglvl, "Run program=%s\n", changer);
285 status = run_program_full_output(changer, timeout, results.addr());
286 Dmsg3(dbglvl, "run_prog: %s stat=%d result=%s", changer, status, results.c_str());
288 loaded = str_to_int32(results.c_str());
290 /* Suppress info when polling */
291 if (!dev->poll && chk_dbglvl(1)) {
292 Jmsg(jcr, M_INFO, 0, _("3302 Autochanger \"loaded? drive %d\", result is Slot %d.\n"),
295 dev->set_slot(loaded);
297 /* Suppress info when polling */
298 if (!dev->poll && chk_dbglvl(1)) {
299 Jmsg(jcr, M_INFO, 0, _("3302 Autochanger \"loaded? drive %d\", result: nothing loaded.\n"),
302 if (loaded == 0) { /* no slot loaded */
304 } else { /* probably some error */
305 dev->clear_slot(); /* unknown */
310 be.set_errno(status);
311 Jmsg(jcr, M_INFO, 0, _("3991 Bad autochanger \"loaded? drive %d\" command: "
312 "ERR=%s.\nResults=%s\n"), drive, be.bstrerror(), results.c_str());
313 Dmsg3(dbglvl, "Error: autochanger loaded? drive %d "
314 "ERR=%s.\nResults=%s\n", drive, be.bstrerror(), results.c_str());
315 loaded = -1; /* force unload */
316 dev->clear_slot(); /* slot unknown */
319 free_pool_memory(changer);
323 static void lock_changer(DCR *dcr)
325 AUTOCHANGER *changer_res = dcr->device->changer_res;
328 Dmsg1(dbglvl, "Locking changer %s\n", changer_res->hdr.name);
329 if ((errstat=rwl_writelock(&changer_res->changer_lock)) != 0) {
331 Jmsg(dcr->jcr, M_ERROR_TERM, 0, _("Lock failure on autochanger. ERR=%s\n"),
332 be.bstrerror(errstat));
337 static void unlock_changer(DCR *dcr)
339 AUTOCHANGER *changer_res = dcr->device->changer_res;
342 Dmsg1(dbglvl, "Unlocking changer %s\n", changer_res->hdr.name);
343 if ((errstat=rwl_writeunlock(&changer_res->changer_lock)) != 0) {
345 Jmsg(dcr->jcr, M_ERROR_TERM, 0, _("Unlock failure on autochanger. ERR=%s\n"),
346 be.bstrerror(errstat));
352 * Unload the volume, if any, in this drive
353 * On entry: loaded == 0 -- nothing to do
354 * loaded < 0 -- check if anything to do
355 * loaded > 0 -- load slot == loaded
357 bool unload_autochanger(DCR *dcr, int loaded)
359 DEVICE *dev = dcr->dev;
361 const char *old_vol_name;
363 uint32_t timeout = dcr->device->max_changer_wait;
370 if (!dev->is_autochanger() || !dcr->device->changer_name ||
371 !dcr->device->changer_command) {
375 /* Virtual disk autochanger */
376 if (dcr->is_virtual_autochanger()) {
382 if (dev->LoadedVolName[0]) {
383 old_vol_name = dev->LoadedVolName;
385 old_vol_name = "*Unknown*";
388 loaded = get_autochanger_loaded_slot(dcr);
389 if (loaded < 0) { /* try again, maybe autochanger error */
390 loaded = get_autochanger_loaded_slot(dcr);
395 POOL_MEM results(PM_MESSAGE);
396 POOLMEM *changer = get_pool_memory(PM_FNAME);
398 _("3307 Issuing autochanger \"unload Volume %s, Slot %d, Drive %d\" command.\n"),
399 old_vol_name, loaded, dev->drive_index);
401 "3307 Issuing autochanger \"unload Volume %s, Slot %d, Drive %d\" command.\n",
402 old_vol_name, loaded, dev->drive_index);
403 slot = dcr->VolCatInfo.Slot;
404 dcr->VolCatInfo.Slot = loaded;
405 changer = edit_device_codes(dcr, changer,
406 dcr->device->changer_command, "unload");
408 Dmsg1(dbglvl, "Run program=%s\n", changer);
409 int stat = run_program_full_output(changer, timeout, results.addr());
410 dcr->VolCatInfo.Slot = slot;
414 Jmsg(jcr, M_INFO, 0, _("3995 Bad autochanger \"unload Volume %s, Slot %d, Drive %d\": "
415 "ERR=%s\nResults=%s\n"),
416 old_vol_name, loaded, dev->drive_index, be.bstrerror(), results.c_str());
417 Dmsg5(dbglvl, "Error: unload Volume %s, Slot %d, Drive %d, bad stats=%s.\nResults=%s\n",
418 old_vol_name, loaded, dev->drive_index,
419 be.bstrerror(), results.c_str());
421 dev->clear_slot(); /* unknown */
423 dev->set_slot(0); /* unload is OK, mark nothing loaded */
425 dev->LoadedVolName[0] = 0; /* clear loaded volume name */
427 free_pool_memory(changer);
438 * Unload the slot if mounted in a different drive
440 static bool unload_other_drive(DCR *dcr, int slot, bool writing)
445 AUTOCHANGER *changer = dcr->dev->device->changer_res;
447 int retries = 0; /* wait for device retries */
451 if (!changer || !changer->device) {
454 if (changer->device->size() == 1) {
459 * We look for the slot number corresponding to the tape
460 * we want in other drives, and if possible, unload
463 Dmsg1(dbglvl, "Begin wiffle through devices looking for slot=%d\n", slot);
465 * foreach_alist(device, changer->device) {
467 * The above fails to loop through all devices. It is
468 * probably a compiler bug.
470 for (i=0; i < changer->device->size(); i++) {
471 device = (DEVRES *)changer->device->get(i);
474 Dmsg0(dbglvl, "No dev attached to device\n");
480 loaded = get_autochanger_loaded_slot(dcr);
481 dcr->set_dev(dev_save);
484 Dmsg4(dbglvl, "Want slot=%d, drive=%d loaded=%d dev=%s\n",
485 slot, dev->drive_index, loaded, dev->print_name());
486 if (loaded == slot) {
491 Dmsg4(dbglvl, "After slot=%d drive=%d loaded=%d dev=%s\n",
492 slot, dev->drive_index, loaded, dev->print_name());
495 Dmsg1(dbglvl, "End wiffle through devices looking for slot=%d\n", slot);
497 Dmsg1(dbglvl, "Slot=%d not found in another device\n", slot);
500 Dmsg3(dbglvl, "Slot=%d drive=%d found in dev=%s\n", slot, dev->drive_index, dev->print_name());
504 * The Volume we want is on another device.
505 * If we want the Volume to read it, and the other device where the
506 * Volume is currently is not open, we simply unload the Volume then
507 * then the subsequent code will load it in the desired drive.
508 * If want to write or the device is open, we attempt to wait for
509 * the Volume to become available.
511 if (writing || dev->is_open()) {
512 if (dev->is_busy()) {
513 Dmsg4(dbglvl, "Vol %s for dev=%s in use dev=%s slot=%d\n",
514 dcr->VolumeName, dcr->dev->print_name(),
515 dev->print_name(), slot);
517 for (int i=0; i < 3; i++) {
518 if (dev->is_busy()) {
519 Dmsg0(40, "Device is busy. Calling wait_for_device()\n");
520 wait_for_device(dcr, retries);
525 if (dev->is_busy()) {
526 Jmsg(dcr->jcr, M_WARNING, 0, _("Volume \"%s\" wanted on %s is in use by device %s\n"),
527 dcr->VolumeName, dcr->dev->print_name(), dev->print_name());
528 Dmsg4(dbglvl, "Vol %s for dev=%s is busy dev=%s slot=%d\n",
529 dcr->VolumeName, dcr->dev->print_name(), dev->print_name(), dev->get_slot());
530 Dmsg2(dbglvl, "num_writ=%d reserv=%d\n", dev->num_writers, dev->num_reserved());
535 return unload_dev(dcr, dev);
539 * Unconditionally unload a specified drive
541 bool unload_dev(DCR *dcr, DEVICE *dev)
545 uint32_t timeout = dcr->device->max_changer_wait;
546 AUTOCHANGER *changer = dcr->dev->device->changer_res;
547 const char *old_vol_name = dcr->VolumeName;
555 save_dev = dcr->dev; /* save dcr device */
556 dcr->set_dev(dev); /* temporarily point dcr at other device */
558 get_autochanger_loaded_slot(dcr);
560 /* Fail if we have no slot to unload */
561 if (dev->get_slot() <= 0) {
562 if (dev->get_slot() < 0) {
563 Dmsg1(dbglvl, "Cannot unload, slot not defined. dev=%s\n",
566 dcr->set_dev(save_dev);
570 save_slot = dcr->VolCatInfo.Slot;
571 dcr->VolCatInfo.Slot = dev->get_slot();
573 POOLMEM *changer_cmd = get_pool_memory(PM_FNAME);
574 POOL_MEM results(PM_MESSAGE);
575 if (old_vol_name[0] == 0) {
576 if (dev->LoadedVolName[0]) {
577 old_vol_name = dev->LoadedVolName;
579 old_vol_name = "*Unknown*";
584 _("3307 Issuing autochanger \"unload Volume %s, Slot %d, Drive %d\" command.\n"),
585 old_vol_name, dev->get_slot(), dev->drive_index);
586 Dmsg3(0/*dbglvl*/, "Issuing autochanger \"unload Volume %s, Slot %d, Drive %d\" command.\n",
587 old_vol_name, dev->get_slot(), dev->drive_index);
589 changer_cmd = edit_device_codes(dcr, changer_cmd,
590 dcr->device->changer_command, "unload");
592 Dmsg2(dbglvl, "close dev=%s reserve=%d\n", dev->print_name(),
593 dev->num_reserved());
594 Dmsg1(dbglvl, "Run program=%s\n", changer_cmd);
595 int stat = run_program_full_output(changer_cmd, timeout, results.addr());
596 dcr->VolCatInfo.Slot = save_slot;
600 Jmsg(jcr, M_INFO, 0, _("3997 Bad autochanger \"unload Volume %s, Slot %d, Drive %d\": ERR=%s.\n"),
601 old_vol_name, dev->get_slot(), dev->drive_index, be.bstrerror());
602 Dmsg5(dbglvl, "Error: unload Volume %s, Slot %d, Drive %d bad stats=%s.\nResults=%s\n",
603 old_vol_name, dev->get_slot(), dev->drive_index,
604 be.bstrerror(), results.c_str());
606 dev->clear_slot(); /* unknown */
608 Dmsg3(dbglvl, "Volume %s, Slot %d unloaded %s\n",
609 old_vol_name, dev->get_slot(), dev->print_name());
610 dev->set_slot(0); /* unload OK, mark nothing loaded */
612 dev->LoadedVolName[0] = 0;
619 dcr->set_dev(save_dev);
620 free_pool_memory(changer_cmd);
627 * List the Volumes that are in the autoloader possibly
628 * with their barcodes.
629 * We assume that it is always the Console that is calling us.
631 bool autochanger_cmd(DCR *dcr, BSOCK *dir, const char *cmd)
633 DEVICE *dev = dcr->dev;
634 uint32_t timeout = dcr->device->max_changer_wait;
637 int len = sizeof_pool_memory(dir->msg) - 1;
640 if (!dev->is_autochanger() || !dcr->device->changer_name ||
641 !dcr->device->changer_command) {
642 if (strcasecmp(cmd, "drives") == 0) {
643 dir->fsend("drives=1\n");
645 dir->fsend(_("3993 Device %s not an autochanger device.\n"),
650 if (strcasecmp(cmd, "drives") == 0) {
651 AUTOCHANGER *changer_res = dcr->device->changer_res;
653 if (changer_res && changer_res->device) {
654 drives = changer_res->device->size();
656 dir->fsend("drives=%d\n", drives);
657 Dmsg1(dbglvl, "drives=%d\n", drives);
661 /* If listing, reprobe changer */
662 if (bstrcasecmp(cmd, "list") || bstrcasecmp(cmd, "listall")) {
663 dcr->dev->set_slot(0);
664 get_autochanger_loaded_slot(dcr);
667 changer = get_pool_memory(PM_FNAME);
669 /* Now issue the command */
670 changer = edit_device_codes(dcr, changer,
671 dcr->device->changer_command, cmd);
672 dir->fsend(_("3306 Issuing autochanger \"%s\" command.\n"), cmd);
673 bpipe = open_bpipe(changer, timeout, "r");
675 dir->fsend(_("3996 Open bpipe failed.\n"));
676 goto bail_out; /* TODO: check if we need to return false */
678 if (bstrcasecmp(cmd, "list") || bstrcasecmp(cmd, "listall")) {
679 /* Get output from changer */
680 while (fgets(dir->msg, len, bpipe->rfd)) {
681 dir->msglen = strlen(dir->msg);
682 Dmsg1(dbglvl, "<stored: %s\n", dir->msg);
685 } else if (strcasecmp(cmd, "slots") == 0 ) {
687 /* For slots command, read a single line */
689 fgets(buf, sizeof(buf)-1, bpipe->rfd);
690 buf[sizeof(buf)-1] = 0;
691 /* Strip any leading space in front of # of slots */
692 for (p=buf; B_ISSPACE(*p); p++)
694 dir->fsend("slots=%s", p);
695 Dmsg1(dbglvl, "<stored: %s", dir->msg);
698 stat = close_bpipe(bpipe);
702 dir->fsend(_("Autochanger error: ERR=%s\n"), be.bstrerror());
707 free_pool_memory(changer);
713 * Edit codes into ChangerCommand
715 * %a = archive device name
716 * %c = changer device name
717 * %d = changer drive index
720 * %l = archive control channel name
727 * omsg = edited output message
728 * imsg = input string containing edit codes (%x)
729 * cmd = command string (load, unload, ...)
732 char *edit_device_codes(DCR *dcr, char *omsg, const char *imsg, const char *cmd)
739 Dmsg1(1800, "edit_device_codes: %s\n", imsg);
740 for (p=imsg; *p; p++) {
747 str = dcr->dev->archive_name();
750 str = NPRT(dcr->device->changer_name);
753 str = NPRT(dcr->device->control_name);
756 sprintf(add, "%d", dcr->dev->drive_index);
763 sprintf(add, "%d", dcr->VolCatInfo.Slot - 1);
767 sprintf(add, "%d", dcr->VolCatInfo.Slot);
770 case 'j': /* Job name */
774 if (dcr->VolCatInfo.VolCatName[0]) {
775 str = dcr->VolCatInfo.VolCatName;
776 } else if (dcr->VolumeName[0]) {
777 str = dcr->VolumeName;
778 } else if (dcr->dev->vol && dcr->dev->vol->vol_name) {
779 str = dcr->dev->vol->vol_name;
781 str = dcr->dev->VolHdr.VolumeName;
785 str = NPRT(dcr->jcr->client_name);
800 Dmsg1(1900, "add_str %s\n", str);
801 pm_strcat(&omsg, (char *)str);
802 Dmsg1(1800, "omsg=%s\n", omsg);
804 Dmsg1(800, "omsg=%s\n", omsg);