2 Bacula® - The Network Backup Solution
4 Copyright (C) 2002-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 * Routines for handling mounting tapes for reading and for
33 * Kern Sibbald, August MMII
38 #include "bacula.h" /* pull in global headers */
39 #include "stored.h" /* pull in Storage Deamon headers */
57 * If release is set, we rewind the current volume,
58 * which we no longer want, and ask the user (console)
59 * to mount the next volume.
61 * Continue trying until we get it, and then ensure
62 * that we can write on it.
64 * This routine returns a 0 only if it is REALLY
65 * impossible to get the requested Volume.
68 bool DCR::mount_next_write_volume()
71 bool ask = false, recycle, autochanger;
75 Dmsg2(150, "Enter mount_next_volume(release=%d) dev=%s\n", unload_device,
78 init_device_wait_timers(dcr);
82 * Attempt to mount the next volume. If something non-fatal goes
83 * wrong, we come back here to re-try (new op messages, re-read
87 Dmsg1(150, "mount_next_vol retry=%d\n", retry);
88 /* Ignore retry if this is poll request */
89 if (!dev->poll && retry++ > 4) {
90 /* Last ditch effort before giving up, force operator to respond */
92 if (!dir_ask_sysop_to_mount_volume(dcr, ST_APPEND)) {
93 Jmsg(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
98 if (job_canceled(jcr)) {
99 Jmsg(jcr, M_FATAL, 0, _("Job %d canceled.\n"), jcr->JobId);
104 Dmsg0(150, "mount_next_volume release=1\n");
106 unload_autochanger(dcr, -1);
107 unload_device = false;
108 ask = true; /* ask operator to mount tape */
112 * See if we are asked to swap the Volume from another device
113 * if so, unload the other device here, and attach the
114 * volume to our drive.
117 dev->vol = swap_dev->vol; /* take its volume */
118 swap_dev->vol = NULL;
119 unload_dev(dcr, swap_dev);
121 dev->vol->clear_swapping();
123 if (!is_suitable_volume_mounted()) {
125 * Get Director's idea of what tape we should have mounted.
128 Dmsg0(200, "Before dir_find_next_appendable_volume.\n");
129 while (!dir_find_next_appendable_volume(dcr)) {
130 Dmsg0(200, "not dir_find_next\n");
131 if (!dir_ask_sysop_to_create_appendable_volume(dcr)) {
134 Dmsg0(200, "Again dir_find_next_append...\n");
137 if (job_canceled(jcr)) {
140 Dmsg3(150, "After find_next_append. Vol=%s Slot=%d Parts=%d\n",
141 VolCatInfo.VolCatName, VolCatInfo.Slot, VolCatInfo.VolCatParts);
144 * Get next volume and ready it for append
145 * This code ensures that the device is ready for
146 * writing. We start from the assumption that there
147 * may not be a tape mounted.
149 * If the device is a file, we create the output
150 * file. If it is a tape, we check the volume name
151 * and move the tape to the end of data.
154 if (autoload_device(dcr, 1, NULL) > 0) {
161 Dmsg1(200, "autoload_dev returns %d\n", autochanger);
163 * If we autochanged to correct Volume or (we have not just
164 * released the Volume AND we can automount) we go ahead
165 * and read the label. If there is no tape in the drive,
166 * we will fail, recurse and ask the operator the next time.
168 if (!unload_device && dev->is_tape() && dev->has_cap(CAP_AUTOMOUNT)) {
169 Dmsg0(150, "(1)Ask=0\n");
170 ask = false; /* don't ask SYSOP this time */
172 /* Don't ask if not removable */
173 if (!dev->is_removable()) {
174 Dmsg0(150, "(2)Ask=0\n");
177 Dmsg2(150, "Ask=%d autochanger=%d\n", ask, autochanger);
178 unload_device = true; /* release next time if we "recurse" */
180 if (ask && !dir_ask_sysop_to_mount_volume(dcr, ST_APPEND)) {
181 Dmsg0(150, "Error return ask_sysop ...\n");
182 goto bail_out; /* error return */
184 if (job_canceled(jcr)) {
187 Dmsg3(150, "want vol=%s devvol=%s dev=%s\n", VolumeName,
188 dev->VolHdr.VolumeName, dev->print_name());
190 if (dev->poll && dev->has_cap(CAP_CLOSEONPOLL)) {
194 /* Ensure the device is open */
195 if (dev->has_cap(CAP_STREAM)) {
196 mode = OPEN_WRITE_ONLY;
198 mode = OPEN_READ_WRITE;
200 /* Try autolabel if enabled */
201 if (dev->open(dcr, mode) < 0) {
202 try_autolabel(false); /* try to create a new volume label */
204 while (dev->open(dcr, mode) < 0) {
205 Dmsg1(150, "open_device failed: ERR=%s\n", dev->bstrerror());
206 if ((dev->is_file() && dev->is_removable()) || dev->is_dvd()) {
208 Dmsg0(150, "call scan_dir_for_vol\n");
210 if (!dev->mount(0)) {
214 if (ok && dev->scan_dir_for_volume(dcr)) {
215 if (dev->open(dcr, mode) >= 0) {
216 break; /* got a valid volume */
219 if (ok && dev->is_dvd()) {
223 if (try_autolabel(false) == try_read_vol) {
224 break; /* created a new volume label */
226 /* If DVD, ignore the error, very often you cannot open the device
227 * (when there is no DVD, or when the one inserted is a wrong one) */
228 if (dev->poll || dev->is_dvd() || dev->is_removable()) {
231 Jmsg(jcr, M_ERROR, 0, _("Could not open device %s: ERR=%s\n"),
232 dev->print_name(), dev->print_errmsg());
238 * Now check the volume label to make sure we have the right tape mounted
242 switch (check_volume_label(ask, autochanger)) {
254 * See if we have a fresh tape or a tape with data.
256 * Note, if the LabelType is PRE_LABEL, it was labeled
257 * but never written. If so, rewrite the label but set as
258 * VOL_LABEL. We rewind and return the label (reconstructed)
259 * in the block so that in the case of a new tape, data can
260 * be appended just after the block label. If we are writing
261 * a second volume, the calling routine will write the label
262 * before writing the overflow block.
264 * If the tape is marked as Recycle, we rewrite the label.
266 recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0;
267 if (dev->VolHdr.LabelType == PRE_LABEL || recycle) {
268 if (!rewrite_volume_label(dcr, recycle)) {
269 mark_volume_in_error();
274 * OK, at this point, we have a valid Bacula label, but
275 * we need to position to the end of the volume, since we are
276 * just now putting it into append mode.
278 Dmsg0(200, "Device previously written, moving to end of data\n");
279 Jmsg(jcr, M_INFO, 0, _("Volume \"%s\" previously written, moving to end of data.\n"),
282 if (!dev->eod(dcr)) {
283 Jmsg(jcr, M_ERROR, 0, _("Unable to position to end of data on device %s: ERR=%s\n"),
284 dev->print_name(), dev->bstrerror());
285 mark_volume_in_error();
288 if (!is_eod_valid()) {
292 dev->VolCatInfo.VolCatMounts++; /* Update mounts */
293 Dmsg1(150, "update volinfo mounts=%d\n", dev->VolCatInfo.VolCatMounts);
294 if (!dir_update_volume_info(dcr, false, false)) {
298 /* Return an empty block */
299 empty_block(block); /* we used it for reading so set for write */
302 Dmsg1(150, "set APPEND, normal return from mount_next_write_volume. dev=%s\n",
313 int DCR::check_volume_label(bool &ask, bool &autochanger)
315 int vol_label_status;
317 * If we are writing to a stream device, ASSUME the volume label
320 if (dev->has_cap(CAP_STREAM)) {
321 vol_label_status = VOL_OK;
322 create_volume_label(dev, VolumeName, "Default", false /* not DVD */);
323 dev->VolHdr.LabelType = PRE_LABEL;
325 vol_label_status = read_dev_volume_label(this);
327 if (job_canceled(jcr)) {
331 Dmsg2(150, "Want dirVol=%s dirStat=%s\n", VolumeName,
332 VolCatInfo.VolCatStatus);
334 * At this point, dev->VolCatInfo has what is in the drive, if anything,
335 * and dcr->VolCatInfo has what the Director wants.
337 switch (vol_label_status) {
339 Dmsg1(150, "Vol OK name=%s\n", VolumeName);
340 dev->VolCatInfo = VolCatInfo; /* structure assignment */
341 break; /* got a Volume */
343 VOLUME_CAT_INFO dcrVolCatInfo, devVolCatInfo;
344 char saveVolumeName[MAX_NAME_LENGTH];
346 /* If not removable, Volume is broken */
347 if (!dev->is_removable()) {
348 Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
349 VolumeName, dev->print_name());
350 mark_volume_in_error();
351 goto check_next_volume;
354 Dmsg1(150, "Vol NAME Error Name=%s\n", VolumeName);
355 /* If polling and got a previous bad name, ignore it */
356 if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolumeName) == 0) {
358 Dmsg1(200, "Vol Name error supress due to poll. Name=%s\n", VolumeName);
359 goto check_next_volume;
362 * OK, we got a different volume mounted. First save the
363 * requested Volume info (dcr) structure, then query if
364 * this volume is really OK. If not, put back the desired
365 * volume name, mark it not in changer and continue.
367 dcrVolCatInfo = VolCatInfo; /* structure assignment */
368 devVolCatInfo = dev->VolCatInfo; /* structure assignment */
369 /* Check if this is a valid Volume in the pool */
370 bstrncpy(saveVolumeName, VolumeName, sizeof(saveVolumeName));
371 bstrncpy(VolumeName, dev->VolHdr.VolumeName, sizeof(VolumeName));
372 if (!dir_get_volume_info(this, GET_VOL_INFO_FOR_WRITE)) {
373 POOL_MEM vol_info_msg;
374 pm_strcpy(vol_info_msg, jcr->dir_bsock->msg); /* save error message */
375 /* Restore desired volume name, note device info out of sync */
376 /* This gets the info regardless of the Pool */
377 bstrncpy(VolumeName, dev->VolHdr.VolumeName, sizeof(VolumeName));
378 if (autochanger && !dir_get_volume_info(this, GET_VOL_INFO_FOR_READ)) {
380 * If we get here, we know we cannot write on the Volume,
381 * and we know that we cannot read it either, so it
382 * is not in the autochanger.
384 mark_volume_not_inchanger();
386 dev->VolCatInfo = devVolCatInfo; /* structure assignment */
387 bstrncpy(dev->BadVolName, dev->VolHdr.VolumeName, sizeof(dev->BadVolName));
388 Jmsg(jcr, M_WARNING, 0, _("Director wanted Volume \"%s\".\n"
389 " Current Volume \"%s\" not acceptable because:\n"
391 dcrVolCatInfo.VolCatName, dev->VolHdr.VolumeName,
392 vol_info_msg.c_str());
394 /* Restore saved DCR before continuing */
395 bstrncpy(VolumeName, saveVolumeName, sizeof(VolumeName));
396 VolCatInfo = dcrVolCatInfo; /* structure assignment */
397 goto check_next_volume;
400 * This was not the volume we expected, but it is OK with
401 * the Director, so use it.
403 Dmsg1(150, "want new name=%s\n", VolumeName);
404 dev->VolCatInfo = VolCatInfo; /* structure assignment */
405 break; /* got a Volume */
407 * At this point, we assume we have a blank tape mounted.
411 Jmsg(jcr, M_FATAL, 0, "%s", jcr->errmsg);
412 mark_volume_in_error();
413 goto check_bail_out; /* we could not write on DVD */
415 /* Fall through wanted */
417 switch (try_autolabel(true)) {
419 goto check_next_volume;
421 goto check_read_volume;
428 /* NOTE! Fall-through wanted. */
431 Dmsg0(200, "VOL_NO_MEDIA or default.\n");
432 /* Send error message */
435 Dmsg1(200, "Msg suppressed by poll: %s\n", jcr->errmsg);
438 /* Needed, so the medium can be changed */
439 if (dev->requires_mount()) {
442 goto check_next_volume;
447 return check_next_vol;
453 return check_read_vol;
458 bool DCR::is_suitable_volume_mounted()
461 /* Volume mounted? */
462 if (dev->VolHdr.VolumeName[0] == 0 || swap_dev || unload_device) {
463 return false; /* no */
465 bstrncpy(VolumeName, dev->VolHdr.VolumeName, sizeof(VolumeName));
466 return dir_get_volume_info(this, GET_VOL_INFO_FOR_WRITE);
472 * Check if the current position on the volume corresponds to
473 * what is in the catalog.
475 bool DCR::is_eod_valid()
478 char ed1[50], ed2[50];
479 if (dev->VolCatInfo.VolCatBytes == dev->part_start + dev->part_size) {
480 Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\""
481 " part=%d size=%s\n"), VolumeName,
482 dev->part, edit_uint64(dev->VolCatInfo.VolCatBytes,ed1));
484 Jmsg(jcr, M_ERROR, 0, _("Bacula cannot write on DVD Volume \"%s\" because: "
485 "The sizes do not match! Volume=%s Catalog=%s\n"),
487 edit_uint64(dev->part_start + dev->part_size, ed1),
488 edit_uint64(dev->VolCatInfo.VolCatBytes, ed2));
489 mark_volume_in_error();
492 } else if (dev->is_tape()) {
494 * Check if we are positioned on the tape at the same place
495 * that the database says we should be.
497 if (dev->VolCatInfo.VolCatFiles == dev->get_file()) {
498 Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\" at file=%d.\n"),
499 VolumeName, dev->get_file());
501 Jmsg(jcr, M_ERROR, 0, _("Bacula cannot write on tape Volume \"%s\" because:\n"
502 "The number of files mismatch! Volume=%u Catalog=%u\n"),
503 VolumeName, dev->get_file(), dev->VolCatInfo.VolCatFiles);
504 mark_volume_in_error();
507 } else if (dev->is_file()) {
508 char ed1[50], ed2[50];
510 pos = dev->lseek(this, (boffset_t)0, SEEK_END);
511 if (dev->VolCatInfo.VolCatBytes == (uint64_t)pos) {
512 Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\""
513 " size=%s\n"), VolumeName,
514 edit_uint64(dev->VolCatInfo.VolCatBytes, ed1));
516 Jmsg(jcr, M_ERROR, 0, _("Bacula cannot write on disk Volume \"%s\" because: "
517 "The sizes do not match! Volume=%s Catalog=%s\n"),
519 edit_uint64(pos, ed1),
520 edit_uint64(dev->VolCatInfo.VolCatBytes, ed2));
521 mark_volume_in_error();
530 * If permitted, we label the device, make sure we can do
531 * it by checking that the VolCatBytes is zero => not labeled,
532 * once the Volume is labeled we don't want to label another
533 * blank tape with the same name. For disk, we go ahead and
534 * label it anyway, because the OS insures that there is only
535 * one Volume with that name.
536 * As noted above, at this point dcr->VolCatInfo has what
537 * the Director wants and dev->VolCatInfo has info on the
538 * previous tape (or nothing).
541 * try_next_vol label failed, look for another volume
542 * try_read_vol labeled volume, now re-read the label
543 * try_error hard error (catalog update)
544 * try_default I couldn't do anything
546 int DCR::try_autolabel(bool opened)
550 if (dev->poll && !dev->is_tape()) {
551 return try_default; /* if polling, don't try to create new labels */
553 /* For a tape require it to be opened and read before labeling */
554 if (!opened && dev->is_tape()) {
557 if (dev->has_cap(CAP_LABEL) && (VolCatInfo.VolCatBytes == 0 ||
558 (!dev->is_tape() && strcmp(VolCatInfo.VolCatStatus,
560 Dmsg0(150, "Create volume label\n");
561 /* Create a new Volume label and write it to the device */
562 if (!write_new_volume_label_to_dev(dcr, VolumeName,
563 pool_name, false, /* no relabel */ false /* defer DVD label */)) {
564 Dmsg0(150, "!write_vol_label\n");
566 mark_volume_in_error();
570 Dmsg0(150, "dir_update_vol_info. Set Append\n");
571 /* Copy Director's info into the device info */
572 dev->VolCatInfo = VolCatInfo; /* structure assignment */
573 if (!dir_update_volume_info(dcr, true, true)) { /* indicate tape labeled */
576 Jmsg(dcr->jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"),
577 VolumeName, dev->print_name());
578 return try_read_vol; /* read label we just wrote */
580 if (!dev->has_cap(CAP_LABEL) && VolCatInfo.VolCatBytes == 0) {
581 Jmsg(jcr, M_WARNING, 0, _("Device %s not configured to autolabel Volumes.\n"),
584 /* If not removable, Volume is broken */
585 if (!dev->is_removable()) {
586 Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
587 VolumeName, dev->print_name());
588 mark_volume_in_error();
596 * Mark volume in error in catalog
598 void DCR::mark_volume_in_error()
600 Jmsg(jcr, M_INFO, 0, _("Marking Volume \"%s\" in Error in Catalog.\n"),
602 dev->VolCatInfo = VolCatInfo; /* structure assignment */
603 bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus));
604 Dmsg0(150, "dir_update_vol_info. Set Error.\n");
605 dir_update_volume_info(this, false, false);
610 * The Volume is not in the correct slot, so mark this
611 * Volume as not being in the Changer.
613 void DCR::mark_volume_not_inchanger()
615 Jmsg(jcr, M_ERROR, 0, _("Autochanger Volume \"%s\" not found in slot %d.\n"
616 " Setting InChanger to zero in catalog.\n"),
617 VolCatInfo.VolCatName, VolCatInfo.Slot);
618 dev->VolCatInfo = VolCatInfo; /* structure assignment */
619 VolCatInfo.InChanger = false;
620 dev->VolCatInfo.InChanger = false;
621 Dmsg0(400, "update vol info in mount\n");
622 dir_update_volume_info(this, true, false); /* set new status */
626 * Either because we are going to hang a new volume, or because
627 * of explicit user request, we release the current volume.
629 void release_volume(DCR *dcr)
632 DEVICE *dev = dcr->dev;
634 Jmsg0(jcr, M_ERROR, 0, _("Hey!!!!! WroteVol non-zero !!!!!\n"));
635 Dmsg0(190, "Hey!!!!! WroteVol non-zero !!!!!\n");
638 * First erase all memory of the current volume
641 dev->block_num = dev->file = 0;
642 dev->EndBlock = dev->EndFile = 0;
643 memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo));
644 // memset(&dcr->VolCatInfo, 0, sizeof(dcr->VolCatInfo));
646 /* Force re-read of label */
647 dev->clear_labeled();
650 dev->label_type = B_BACULA_LABEL;
651 // dcr->VolumeName[0] = 0;
653 if (dev->is_open() && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
657 /* If we have not closed the device, then at least rewind the tape */
658 if (dev->is_open()) {
659 dev->offline_or_rewind();
661 Dmsg0(190, "release_volume\n");
665 * If we are reading, we come here at the end of the tape
666 * and see if there are more volumes to be mounted.
668 bool mount_next_read_volume(DCR *dcr)
670 DEVICE *dev = dcr->dev;
672 Dmsg2(90, "NumReadVolumes=%d CurReadVolume=%d\n", jcr->NumReadVolumes, jcr->CurReadVolume);
674 volume_unused(dcr); /* release current volume */
676 * End Of Tape -- mount next Volume (if another specified)
678 if (jcr->NumReadVolumes > 1 && jcr->CurReadVolume < jcr->NumReadVolumes) {
680 if (!acquire_device_for_read(dcr)) {
681 Jmsg2(jcr, M_FATAL, 0, _("Cannot open Dev=%s, Vol=%s\n"), dev->print_name(),
685 return true; /* next volume mounted */
687 Dmsg0(90, "End of Device reached.\n");