1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2002-2012 Free Software Foundation Europe e.V.
5 Copyright (C) 2011-2012 Planets Communications B.V.
6 Copyright (C) 2013-2019 Bareos GmbH & Co. KG
7
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
11 in the file LICENSE.
12
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 Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero 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
21 02110-1301, USA.
22 */
23 /*
24 * Kern Sibbald, August MMII
25 */
26 /**
27 * @file
28 * Routines for handling mounting tapes for reading and for writing.
29 */
30
31 #include "include/bareos.h" /* pull in global headers */
32 #include "stored/stored.h" /* pull in Storage Daemon headers */
33 #include "stored/acquire.h"
34 #include "stored/autochanger.h"
35 #include "stored/jcr_private.h"
36 #include "stored/label.h"
37 #include "lib/edit.h"
38 #include "include/jcr.h"
39 #include "lib/bsock.h"
40
41 namespace storagedaemon {
42
43 static pthread_mutex_t mount_mutex = PTHREAD_MUTEX_INITIALIZER;
44
45 enum
46 {
47 try_next_vol = 1,
48 try_read_vol,
49 try_error,
50 try_default
51 };
52
53 enum
54 {
55 check_next_vol = 1,
56 check_ok,
57 check_read_vol,
58 check_error
59 };
60
61 /**
62 * If release is set, we rewind the current volume,
63 * which we no longer want, and ask the user (console)
64 * to mount the next volume.
65 *
66 * Continue trying until we get it, and then ensure
67 * that we can write on it.
68 *
69 * This routine returns a 0 only if it is REALLY
70 * impossible to get the requested Volume.
71 *
72 * This routine is entered with the device blocked, but not
73 * locked.
74 *
75 */
MountNextWriteVolume()76 bool DeviceControlRecord::MountNextWriteVolume()
77 {
78 int retry = 0;
79 bool ask = false, recycle, autochanger;
80 int mode;
81 DeviceControlRecord* dcr = this;
82
83 Dmsg2(150, "Enter mount_next_volume(release=%d) dev=%s\n", dev->MustUnload(),
84 dev->print_name());
85
86 InitDeviceWaitTimers(dcr);
87
88 P(mount_mutex);
89
90 /*
91 * Attempt to mount the next volume. If something non-fatal goes
92 * wrong, we come back here to re-try (new op messages, re-read
93 * Volume, ...)
94 */
95
96 mount_next_vol:
97 Dmsg1(150, "mount_next_vol retry=%d\n", retry);
98 /*
99 * Ignore retry if this is poll request
100 */
101 if (retry++ > 4) {
102 /*
103 * Last ditch effort before giving up, force operator to respond
104 */
105 VolCatInfo.Slot = 0;
106 V(mount_mutex);
107 if (!dcr->DirAskSysopToMountVolume(ST_APPENDREADY)) {
108 Jmsg(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
109 dev->print_name());
110 goto no_lock_bail_out;
111 }
112 P(mount_mutex);
113 Dmsg1(150, "Continue after dir_ask_sysop_to_mount. must_load=%d\n",
114 dev->must_load());
115 }
116
117 if (JobCanceled(jcr)) {
118 Jmsg(jcr, M_FATAL, 0, _("Job %d canceled.\n"), jcr->JobId);
119 goto bail_out;
120 }
121 recycle = false;
122
123 if (dev->MustUnload()) { ask = true; /* ask operator to mount tape */ }
124
125 DoUnload();
126 DoSwapping(true /*IsWriting*/);
127 DoLoad(true /*IsWriting*/);
128
129 if (!find_a_volume()) { goto bail_out; }
130
131 if (JobCanceled(jcr)) { goto bail_out; }
132
133 Dmsg2(150, "After find_next_append. Vol=%s Slot=%d\n", getVolCatName(),
134 VolCatInfo.Slot);
135
136 /*
137 * Get next volume and ready it for append
138 * This code ensures that the device is ready for
139 * writing. We start from the assumption that there
140 * may not be a tape mounted.
141 *
142 * If the device is a file, we create the output
143 * file. If it is a tape, we check the volume name
144 * and move the tape to the end of data.
145 */
146 dcr->setVolCatInfo(false); /* out of date when Vols unlocked */
147
148 /*
149 * See if this is a retry of the mounting of the next volume.
150 * If the device is already open close it first as otherwise we could
151 * potentially write to an already open device a new volume label.
152 * This is only interesting for non tape devices.
153 */
154 if (!dev->IsTape()) {
155 if (retry && dev->IsOpen()) { dev->close(dcr); }
156 }
157
158 switch (AutoloadDevice(dcr, true /* writing */, NULL)) {
159 case -3:
160 Dmsg0(100, "Wait after a unsuccessful tape load (empty slot).\n");
161 Jmsg0(jcr, M_WARNING, 0,
162 "Wait after a unsuccessful tape load (empty slot).\n");
163 Bmicrosleep(1, 0);
164 dev->VolHdr.VolumeName[0] = 0;
165 dev->vol = 0; /* do not free volume here because in this case
166 * it is still on the vol_list chain for another job */
167 goto mount_next_vol;
168 break;
169 case -2:
170 case -1:
171 /*
172 * -1 => error on autochanger
173 */
174 autochanger = false;
175 VolCatInfo.Slot = 0;
176 ask = retry >= 2;
177 break;
178 case 0:
179 /*
180 * 0 => failure (no changer available)
181 */
182 autochanger = false;
183 VolCatInfo.Slot = 0;
184
185 /*
186 * If the VolCatInfo.InChanger flag is not set we are trying to use a
187 * volume that is not in the autochanger so that means we need to ask the
188 * operator to mount it.
189 */
190 if (dev->IsAutochanger() && !VolCatInfo.InChanger) {
191 ask = true;
192 } else {
193 ask = retry >= 2;
194 }
195 break;
196 default:
197 /*
198 * Success
199 */
200 autochanger = true;
201 ask = false;
202 break;
203 }
204 Dmsg1(150, "autoLoadDev returns %d\n", autochanger);
205
206 /*
207 * If we autochanged to correct Volume or (we have not just
208 * released the Volume AND we can automount) we go ahead
209 * and read the label. If there is no tape in the drive,
210 * we will fail, recurse and ask the operator the next time.
211 */
212 if (!dev->MustUnload() && dev->IsTape() && dev->HasCap(CAP_AUTOMOUNT)) {
213 Dmsg0(250, "(1)Ask=0\n");
214 ask = false; /* don't ask SYSOP this time */
215 }
216
217 /*
218 * Don't ask if not removable
219 */
220 if (!dev->IsRemovable()) {
221 Dmsg0(250, "(2)Ask=0\n");
222 ask = false;
223 }
224 Dmsg2(250, "Ask=%d autochanger=%d\n", ask, autochanger);
225
226 if (ask) {
227 V(mount_mutex);
228 dcr->setVolCatInfo(false); /* out of date when Vols unlocked */
229 if (!dcr->DirAskSysopToMountVolume(ST_APPENDREADY)) {
230 Dmsg0(150, "Error return ask_sysop ...\n");
231 goto no_lock_bail_out;
232 }
233 P(mount_mutex);
234 }
235
236 if (JobCanceled(jcr)) { goto bail_out; }
237
238 Dmsg3(150, "want vol=%s devvol=%s dev=%s\n", VolumeName,
239 dev->VolHdr.VolumeName, dev->print_name());
240
241 if (dev->poll && dev->HasCap(CAP_CLOSEONPOLL)) {
242 dev->close(dcr);
243 FreeVolume(dev);
244 }
245
246 /*
247 * Ensure the device is open
248 */
249 if (dev->HasCap(CAP_STREAM)) {
250 mode = OPEN_WRITE_ONLY;
251 } else {
252 mode = OPEN_READ_WRITE;
253 }
254
255 /*
256 * Try autolabel if enabled
257 */
258 if (!dev->open(dcr, mode)) {
259 TryAutolabel(false); /* try to create a new volume label */
260 }
261
262 while (!dev->open(dcr, mode)) {
263 Dmsg1(150, "OpenDevice failed: ERR=%s\n", dev->bstrerror());
264 if (dev->IsFile() && dev->IsRemovable()) {
265 bool ok = true;
266 Dmsg0(150, "call scan_dir_for_vol\n");
267 if (ok && dev->ScanDirForVolume(dcr)) {
268 if (dev->open(dcr, mode)) { break; /* got a valid volume */ }
269 }
270 }
271 if (TryAutolabel(false) == try_read_vol) {
272 break; /* created a new volume label */
273 }
274 Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
275 dev->print_name(), dcr->VolumeName, dev->bstrerror());
276 Dmsg0(50, "SetUnload\n");
277 dev->SetUnload(); /* force ask sysop */
278 ask = true;
279 Dmsg0(150, "goto mount_next_vol\n");
280 goto mount_next_vol;
281 }
282
283 /*
284 * Now check the volume label to make sure we have the right tape mounted
285 */
286 read_volume:
287 switch (CheckVolumeLabel(ask, autochanger)) {
288 case check_next_vol:
289 Dmsg0(50, "SetUnload\n");
290 dev->SetUnload(); /* want a different Volume */
291 Dmsg0(150, "goto mount_next_vol\n");
292 goto mount_next_vol;
293 case check_read_vol:
294 goto read_volume;
295 case check_error:
296 goto bail_out;
297 case check_ok:
298 break;
299 }
300 /*
301 * Check that volcatinfo is good
302 */
303 if (!dev->haveVolCatInfo()) {
304 Dmsg0(210, "Do not have volcatinfo\n");
305 if (!find_a_volume()) { goto mount_next_vol; }
306
307 dev->VolCatInfo = VolCatInfo; /* structure assignment */
308
309 /*
310 * Apply the Volume Blocksizes to device
311 */
312 dcr->VolMinBlocksize = VolCatInfo.VolMinBlocksize;
313 dcr->VolMaxBlocksize = VolCatInfo.VolMaxBlocksize;
314 Dmsg3(200,
315 "applying vol block sizes to device %s: dcr->VolMinBlocksize set to "
316 "%u, dcr->VolMaxBlocksize set to %u\n",
317 dev->print_name(), dcr->VolMinBlocksize, dcr->VolMaxBlocksize);
318
319 /*
320 * Set the block sizes of the dcr in the device.
321 */
322 dev->SetBlocksizes(dcr);
323 }
324
325 /*
326 * See if we have a fresh tape or a tape with data.
327 *
328 * Note, if the LabelType is PRE_LABEL, it was labeled
329 * but never written. If so, rewrite the label but set as
330 * VOL_LABEL. We rewind and return the label (reconstructed)
331 * in the block so that in the case of a new tape, data can
332 * be appended just after the block label. If we are writing
333 * a second volume, the calling routine will write the label
334 * before writing the overflow block.
335 *
336 * If the tape is marked as Recycle, we rewrite the label.
337 */
338 recycle = bstrcmp(dev->VolCatInfo.VolCatStatus, "Recycle");
339 if (dev->VolHdr.LabelType == PRE_LABEL || recycle) {
340 if (!dcr->RewriteVolumeLabel(recycle)) {
341 MarkVolumeInError();
342 goto mount_next_vol;
343 }
344 } else {
345 /*
346 * OK, at this point, we have a valid Bareos label, but
347 * we need to position to the end of the volume, since we are
348 * just now putting it into append mode.
349 */
350 Dmsg1(
351 100,
352 "Device previously written, moving to end of data. Expect %lld bytes\n",
353 dev->VolCatInfo.VolCatBytes);
354 Jmsg(jcr, M_INFO, 0,
355 _("Volume \"%s\" previously written, moving to end of data.\n"),
356 VolumeName);
357
358 if (!dev->eod(dcr)) {
359 Dmsg2(050, "Unable to position to end of data on device %s: ERR=%s\n",
360 dev->print_name(), dev->bstrerror());
361 Jmsg(jcr, M_ERROR, 0,
362 _("Unable to position to end of data on device %s: ERR=%s\n"),
363 dev->print_name(), dev->bstrerror());
364 MarkVolumeInError();
365 goto mount_next_vol;
366 }
367 if (!is_eod_valid()) {
368 Dmsg0(100, "goto mount_next_vol\n");
369 goto mount_next_vol;
370 }
371
372 dev->VolCatInfo.VolCatMounts++; /* Update mounts */
373 Dmsg1(150, "update volinfo mounts=%d\n", dev->VolCatInfo.VolCatMounts);
374 if (!dcr->DirUpdateVolumeInfo(false, false)) { goto bail_out; }
375
376 /* Return an empty block */
377 EmptyBlock(block); /* we used it for reading so set for write */
378 }
379 dev->SetAppend();
380 Dmsg1(150, "set APPEND, normal return from MountNextWriteVolume. dev=%s\n",
381 dev->print_name());
382
383 V(mount_mutex);
384 return true;
385
386 bail_out:
387 V(mount_mutex);
388
389 no_lock_bail_out:
390 return false;
391 }
392
393 /**
394 * This routine is meant to be called once the first pass
395 * to ensure that we have a candidate volume to mount.
396 * Otherwise, we ask the sysop to created one.
397 *
398 * Note, mount_mutex is already locked on entry and thus
399 * must remain locked on exit from this function.
400 */
find_a_volume()401 bool DeviceControlRecord::find_a_volume()
402 {
403 DeviceControlRecord* dcr = this;
404
405 if (!IsSuitableVolumeMounted()) {
406 bool have_vol = false;
407
408 /*
409 * Do we have a candidate volume?
410 */
411 if (dev->vol) {
412 bstrncpy(VolumeName, dev->vol->vol_name, sizeof(VolumeName));
413 have_vol = dcr->DirGetVolumeInfo(GET_VOL_INFO_FOR_WRITE);
414 }
415
416 /*
417 * Get Director's idea of what tape we should have mounted, in
418 * dcr->VolCatInfo
419 */
420 if (!have_vol) {
421 Dmsg0(200, "Before DirFindNextAppendableVolume.\n");
422 while (!dcr->DirFindNextAppendableVolume()) {
423 Dmsg0(200, "not dir_find_next\n");
424 if (JobCanceled(jcr)) { return false; }
425 V(mount_mutex);
426 if (!dcr->DirAskSysopToCreateAppendableVolume()) {
427 P(mount_mutex);
428 return false;
429 }
430 P(mount_mutex);
431 if (JobCanceled(jcr)) { return false; }
432 Dmsg0(150, "Again dir_find_next_append...\n");
433 }
434 }
435 }
436
437 if (dcr->haveVolCatInfo()) { return true; }
438
439 return dcr->DirGetVolumeInfo(GET_VOL_INFO_FOR_WRITE);
440 }
441
CheckVolumeLabel(bool & ask,bool & autochanger)442 int DeviceControlRecord::CheckVolumeLabel(bool& ask, bool& autochanger)
443 {
444 DeviceControlRecord* dcr = this;
445 int vol_label_status;
446
447 /*
448 * If we are writing to a stream device, ASSUME the volume label
449 * is correct.
450 */
451 if (dev->HasCap(CAP_STREAM)) {
452 vol_label_status = VOL_OK;
453 CreateVolumeLabel(dev, VolumeName, "Default");
454 dev->VolHdr.LabelType = PRE_LABEL;
455 } else {
456 vol_label_status = ReadDevVolumeLabel(dcr);
457 }
458 if (JobCanceled(jcr)) { goto check_bail_out; }
459
460 Dmsg2(150, "Want dirVol=%s dirStat=%s\n", VolumeName,
461 VolCatInfo.VolCatStatus);
462
463 /*
464 * At this point, dev->VolCatInfo has what is in the drive, if anything,
465 * and dcr->VolCatInfo has what the Director wants.
466 */
467 switch (vol_label_status) {
468 case VOL_OK:
469 Dmsg1(150, "Vol OK name=%s\n", dev->VolHdr.VolumeName);
470 dev->VolCatInfo = VolCatInfo; /* structure assignment */
471 break; /* got a Volume */
472 case VOL_NAME_ERROR: {
473 VolumeCatalogInfo dcrVolCatInfo, devVolCatInfo;
474 char saveVolumeName[MAX_NAME_LENGTH];
475
476 Dmsg2(150, "Vol NAME Error Have=%s, want=%s\n", dev->VolHdr.VolumeName,
477 VolumeName);
478 if (dev->IsVolumeToUnload()) {
479 ask = true;
480 goto check_next_volume;
481 }
482
483 /* If not removable, Volume is broken */
484 if (!dev->IsRemovable()) {
485 Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
486 VolumeName, dev->print_name());
487 MarkVolumeInError();
488 goto check_next_volume;
489 }
490
491 /*
492 * OK, we got a different volume mounted. First save the
493 * requested Volume info (dcr) structure, then query if
494 * this volume is really OK. If not, put back the desired
495 * volume name, mark it not in changer and continue.
496 */
497 dcrVolCatInfo = VolCatInfo; /* structure assignment */
498 devVolCatInfo = dev->VolCatInfo; /* structure assignment */
499 /* Check if this is a valid Volume in the pool */
500 bstrncpy(saveVolumeName, VolumeName, sizeof(saveVolumeName));
501 bstrncpy(VolumeName, dev->VolHdr.VolumeName, sizeof(VolumeName));
502 if (!dcr->DirGetVolumeInfo(GET_VOL_INFO_FOR_WRITE)) {
503 PoolMem vol_info_msg;
504 PmStrcpy(vol_info_msg, jcr->dir_bsock->msg); /* save error message */
505 /* Restore desired volume name, note device info out of sync */
506 /* This gets the info regardless of the Pool */
507 bstrncpy(VolumeName, dev->VolHdr.VolumeName, sizeof(VolumeName));
508 if (autochanger && !dcr->DirGetVolumeInfo(GET_VOL_INFO_FOR_READ)) {
509 /*
510 * If we get here, we know we cannot write on the Volume,
511 * and we know that we cannot read it either, so it
512 * is not in the autochanger.
513 */
514 mark_volume_not_inchanger();
515 }
516 dev->VolCatInfo = devVolCatInfo; /* structure assignment */
517 dev->SetUnload(); /* unload this volume */
518 Jmsg(jcr, M_WARNING, 0,
519 _("Director wanted Volume \"%s\".\n"
520 " Current Volume \"%s\" not acceptable because:\n"
521 " %s"),
522 dcrVolCatInfo.VolCatName, dev->VolHdr.VolumeName,
523 vol_info_msg.c_str());
524 ask = true;
525 /* Restore saved DeviceControlRecord before continuing */
526 bstrncpy(VolumeName, saveVolumeName, sizeof(VolumeName));
527 VolCatInfo = dcrVolCatInfo; /* structure assignment */
528 goto check_next_volume;
529 }
530 /*
531 * This was not the volume we expected, but it is OK with
532 * the Director, so use it.
533 */
534 Dmsg1(150, "Got new Volume name=%s\n", VolumeName);
535 dev->VolCatInfo = VolCatInfo; /* structure assignment */
536 Dmsg1(100, "Call reserve_volume=%s\n", dev->VolHdr.VolumeName);
537 if (reserve_volume(dcr, dev->VolHdr.VolumeName) == NULL) {
538 Jmsg2(jcr, M_WARNING, 0, _("Could not reserve volume %s on %s\n"),
539 dev->VolHdr.VolumeName, dev->print_name());
540 ask = true;
541 dev->setVolCatInfo(false);
542 setVolCatInfo(false);
543 goto check_next_volume;
544 }
545 break; /* got a Volume */
546 }
547 /*
548 * At this point, we assume we have a blank tape mounted.
549 */
550 case VOL_IO_ERROR:
551 /* Fall through wanted */
552 case VOL_NO_LABEL:
553 switch (TryAutolabel(true)) {
554 case try_next_vol:
555 goto check_next_volume;
556 case try_read_vol:
557 goto check_read_volume;
558 case try_error:
559 goto check_bail_out;
560 case try_default:
561 break;
562 }
563 /* NOTE! Fall-through wanted. */
564 case VOL_NO_MEDIA:
565 default:
566 Dmsg0(200, "VOL_NO_MEDIA or default.\n");
567 /* Send error message */
568 if (!dev->poll) {
569 } else {
570 Dmsg1(200, "Msg suppressed by poll: %s\n", jcr->errmsg);
571 }
572 ask = true;
573 /* Needed, so the medium can be changed */
574 if (dev->RequiresMount()) {
575 dev->close(dcr);
576 FreeVolume(dev);
577 }
578 goto check_next_volume;
579 }
580 return check_ok;
581
582 check_next_volume:
583 dev->setVolCatInfo(false);
584 setVolCatInfo(false);
585 return check_next_vol;
586
587 check_bail_out:
588 return check_error;
589
590 check_read_volume:
591 return check_read_vol;
592 }
593
IsSuitableVolumeMounted()594 bool DeviceControlRecord::IsSuitableVolumeMounted()
595 {
596 /* Volume mounted? */
597 if (dev->VolHdr.VolumeName[0] == 0 || dev->swap_dev || dev->MustUnload()) {
598 return false; /* no */
599 }
600 bstrncpy(VolumeName, dev->VolHdr.VolumeName, sizeof(VolumeName));
601 return DirGetVolumeInfo(GET_VOL_INFO_FOR_WRITE);
602 }
603
DoUnload()604 bool DeviceControlRecord::DoUnload()
605 {
606 DeviceControlRecord* dcr = this;
607
608 if (GeneratePluginEvent(jcr, bsdEventVolumeUnload, dcr) != bRC_OK) {
609 return false;
610 }
611
612 if (dev->MustUnload()) {
613 Dmsg1(100, "MustUnload release %s\n", dev->print_name());
614 ReleaseVolume();
615 }
616 return true;
617 }
618
DoLoad(bool IsWriting)619 bool DeviceControlRecord::DoLoad(bool IsWriting)
620 {
621 DeviceControlRecord* dcr = this;
622 bool retval = false;
623
624 if (dev->must_load()) {
625 Dmsg1(100, "Must load %s\n", dev->print_name());
626 if (AutoloadDevice(dcr, IsWriting, NULL) > 0) {
627 dev->clear_load();
628 retval = true;
629 }
630 } else {
631 retval = true;
632 }
633
634 if (GeneratePluginEvent(jcr, bsdEventVolumeLoad, dcr) != bRC_OK) {
635 retval = false;
636 }
637
638 return retval;
639 }
640
DoSwapping(bool IsWriting)641 void DeviceControlRecord::DoSwapping(bool IsWriting)
642 {
643 DeviceControlRecord* dcr = this;
644
645 /*
646 * See if we are asked to swap the Volume from another device
647 * if so, unload the other device here, and attach the
648 * volume to our drive.
649 */
650 if (dev->swap_dev) {
651 if (dev->swap_dev->MustUnload()) {
652 if (dev->vol) { dev->swap_dev->SetSlotNumber(dev->vol->GetSlot()); }
653 Dmsg2(100, "Swap unloading slot=%d %s\n", dev->swap_dev->GetSlot(),
654 dev->swap_dev->print_name());
655 UnloadDev(dcr, dev->swap_dev);
656 }
657 if (dev->vol) {
658 dev->vol->ClearSwapping();
659 Dmsg1(100, "=== set in_use vol=%s\n", dev->vol->vol_name);
660 dev->vol->SetInUse();
661 dev->VolHdr.VolumeName[0] = 0; /* don't yet have right Volume */
662 } else {
663 Dmsg1(100, "No vol on dev=%s\n", dev->print_name());
664 }
665 if (dev->swap_dev->vol) {
666 Dmsg2(100, "Vol=%s on dev=%s\n", dev->swap_dev->vol->vol_name,
667 dev->swap_dev->print_name());
668 }
669 Dmsg2(100, "Set swap_dev=NULL for dev=%s swap_dev=%s\n", dev->print_name(),
670 dev->swap_dev->print_name());
671 dev->swap_dev = NULL;
672 } else {
673 Dmsg0(100, "No swap_dev set\n");
674 }
675 }
676
677 /**
678 * Check if the current position on the volume corresponds to what is in the
679 * catalog.
680 */
is_eod_valid()681 bool DeviceControlRecord::is_eod_valid()
682 {
683 DeviceControlRecord* dcr = this;
684
685 if (dev->IsTape()) {
686 /*
687 * Check if we are positioned on the tape at the same place
688 * that the database says we should be.
689 */
690 if (dev->VolCatInfo.VolCatFiles == dev->GetFile()) {
691 Jmsg(jcr, M_INFO, 0,
692 _("Ready to append to end of Volume \"%s\" at file=%d.\n"),
693 VolumeName, dev->GetFile());
694 } else if (dev->GetFile() > dev->VolCatInfo.VolCatFiles) {
695 Jmsg(jcr, M_WARNING, 0,
696 _("For Volume \"%s\":\n"
697 "The number of files mismatch! Volume=%u Catalog=%u\n"
698 "Correcting Catalog\n"),
699 VolumeName, dev->GetFile(), dev->VolCatInfo.VolCatFiles);
700 dev->VolCatInfo.VolCatFiles = dev->GetFile();
701 dev->VolCatInfo.VolCatBlocks = dev->GetBlockNum();
702 if (!dcr->DirUpdateVolumeInfo(false, true)) {
703 Jmsg(jcr, M_WARNING, 0, _("Error updating Catalog\n"));
704 MarkVolumeInError();
705 return false;
706 }
707 } else {
708 Jmsg(jcr, M_ERROR, 0,
709 _("Bareos cannot write on tape Volume \"%s\" because:\n"
710 "The number of files mismatch! Volume=%u Catalog=%u\n"),
711 VolumeName, dev->GetFile(), dev->VolCatInfo.VolCatFiles);
712 MarkVolumeInError();
713 return false;
714 }
715 } else if (dev->IsFile()) {
716 char ed1[50], ed2[50];
717
718 boffset_t pos;
719 pos = dev->lseek(dcr, (boffset_t)0, SEEK_CUR);
720 if (dev->VolCatInfo.VolCatBytes == (uint64_t)pos) {
721 Jmsg(jcr, M_INFO, 0,
722 _("Ready to append to end of Volume \"%s\""
723 " size=%s\n"),
724 VolumeName, edit_uint64(dev->VolCatInfo.VolCatBytes, ed1));
725 } else if ((uint64_t)pos > dev->VolCatInfo.VolCatBytes) {
726 Jmsg(jcr, M_WARNING, 0,
727 _("For Volume \"%s\":\n"
728 "The sizes do not match! Volume=%s Catalog=%s\n"
729 "Correcting Catalog\n"),
730 VolumeName, edit_uint64(pos, ed1),
731 edit_uint64(dev->VolCatInfo.VolCatBytes, ed2));
732 dev->VolCatInfo.VolCatBytes = (uint64_t)pos;
733 dev->VolCatInfo.VolCatFiles = (uint32_t)(pos >> 32);
734 if (!dcr->DirUpdateVolumeInfo(false, true)) {
735 Jmsg(jcr, M_WARNING, 0, _("Error updating Catalog\n"));
736 MarkVolumeInError();
737 return false;
738 }
739 } else {
740 Mmsg(jcr->errmsg,
741 _("Bareos cannot write on disk Volume \"%s\" because: "
742 "The sizes do not match! Volume=%s Catalog=%s\n"),
743 VolumeName, edit_uint64(pos, ed1),
744 edit_uint64(dev->VolCatInfo.VolCatBytes, ed2));
745 Jmsg(jcr, M_ERROR, 0, jcr->errmsg);
746 Dmsg0(050, jcr->errmsg);
747 MarkVolumeInError();
748 return false;
749 }
750 } else if (dev->IsFifo() || dev->IsVtl()) {
751 return true;
752 } else {
753 Mmsg1(
754 jcr->errmsg,
755 _("Don't know how to check if EOD is valid for a device of type %d\n"),
756 dev->dev_type);
757 Jmsg(jcr, M_ERROR, 0, jcr->errmsg);
758 Dmsg0(050, jcr->errmsg);
759 return false;
760 }
761
762 return true;
763 }
764
765 /**
766 * If permitted, we label the device, make sure we can do
767 * it by checking that the VolCatBytes is zero => not labeled,
768 * once the Volume is labeled we don't want to label another
769 * blank tape with the same name. For disk, we go ahead and
770 * label it anyway, because the OS insures that there is only
771 * one Volume with that name.
772 * As noted above, at this point dcr->VolCatInfo has what
773 * the Director wants and dev->VolCatInfo has info on the
774 * previous tape (or nothing).
775 *
776 * Return codes are:
777 * try_next_vol label failed, look for another volume
778 * try_read_vol labeled volume, now re-read the label
779 * try_error hard error (catalog update)
780 * try_default I couldn't do anything
781 */
TryAutolabel(bool opened)782 int DeviceControlRecord::TryAutolabel(bool opened)
783 {
784 DeviceControlRecord* dcr = this;
785
786 if (dev->poll && !dev->IsTape()) {
787 return try_default; /* if polling, don't try to create new labels */
788 }
789 /* For a tape require it to be opened and read before labeling */
790 if (!opened && dev->IsTape()) { return try_default; }
791 if (dev->HasCap(CAP_LABEL) &&
792 (VolCatInfo.VolCatBytes == 0 ||
793 (!dev->IsTape() && bstrcmp(VolCatInfo.VolCatStatus, "Recycle")))) {
794 Dmsg0(150, "Create volume label\n");
795 /* Create a new Volume label and write it to the device */
796 if (!WriteNewVolumeLabelToDev(dcr, VolumeName, pool_name,
797 false /* no relabel */)) {
798 Dmsg2(150, "write_vol_label failed. vol=%s, pool=%s\n", VolumeName,
799 pool_name);
800 if (opened) { MarkVolumeInError(); }
801 return try_next_vol;
802 }
803 Dmsg0(150, "dir_update_vol_info. Set Append\n");
804 /* Copy Director's info into the device info */
805 dev->VolCatInfo = VolCatInfo; /* structure assignment */
806 if (!dcr->DirUpdateVolumeInfo(true, true)) { /* indicate tape labeled */
807 return try_error;
808 }
809 Jmsg(dcr->jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"),
810 VolumeName, dev->print_name());
811 return try_read_vol; /* read label we just wrote */
812 }
813 if (!dev->HasCap(CAP_LABEL) && VolCatInfo.VolCatBytes == 0) {
814 Jmsg(jcr, M_WARNING, 0,
815 _("Device %s not configured to autolabel Volumes.\n"),
816 dev->print_name());
817 }
818 /* If not removable, Volume is broken */
819 if (!dev->IsRemovable()) {
820 Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"), VolumeName,
821 dev->print_name());
822 MarkVolumeInError();
823 return try_next_vol;
824 }
825 return try_default;
826 }
827
828 /**
829 * Mark volume in error in catalog
830 */
MarkVolumeInError()831 void DeviceControlRecord::MarkVolumeInError()
832 {
833 DeviceControlRecord* dcr = this;
834
835 Jmsg(jcr, M_INFO, 0, _("Marking Volume \"%s\" in Error in Catalog.\n"),
836 VolumeName);
837 dev->VolCatInfo = VolCatInfo; /* structure assignment */
838 bstrncpy(dev->VolCatInfo.VolCatStatus, "Error",
839 sizeof(dev->VolCatInfo.VolCatStatus));
840 Dmsg0(150, "dir_update_vol_info. Set Error.\n");
841 dcr->DirUpdateVolumeInfo(false, false);
842 VolumeUnused(dcr);
843 Dmsg0(50, "SetUnload\n");
844 dev->SetUnload(); /* must get a new volume */
845 }
846
847 /**
848 * The Volume is not in the correct slot, so mark this
849 * Volume as not being in the Changer.
850 */
mark_volume_not_inchanger()851 void DeviceControlRecord::mark_volume_not_inchanger()
852 {
853 DeviceControlRecord* dcr = this;
854
855 Jmsg(jcr, M_ERROR, 0,
856 _("Autochanger Volume \"%s\" not found in slot %d.\n"
857 " Setting InChanger to zero in catalog.\n"),
858 getVolCatName(), VolCatInfo.Slot);
859 dev->VolCatInfo = VolCatInfo; /* structure assignment */
860 VolCatInfo.InChanger = false;
861 dev->VolCatInfo.InChanger = false;
862 Dmsg0(400, "update vol info in mount\n");
863 dcr->DirUpdateVolumeInfo(true, false); /* set new status */
864 }
865
866 /**
867 * Either because we are going to hang a new volume, or because
868 * of explicit user request, we release the current volume.
869 */
ReleaseVolume()870 void DeviceControlRecord::ReleaseVolume()
871 {
872 DeviceControlRecord* dcr = this;
873
874 UnloadAutochanger(dcr, -1);
875
876 GeneratePluginEvent(jcr, bsdEventVolumeUnload, dcr);
877
878 if (WroteVol) {
879 Jmsg0(jcr, M_ERROR, 0, _("Hey!!!!! WroteVol non-zero !!!!!\n"));
880 Pmsg0(190, "Hey!!!!! WroteVol non-zero !!!!!\n");
881 }
882 /*
883 * First erase all memory of the current volume
884 */
885 FreeVolume(dev);
886 dev->block_num = dev->file = 0;
887 dev->EndBlock = dev->EndFile = 0;
888 VolumeCatalogInfo empty_VolumeCatalogInfo;
889 dev->VolCatInfo = empty_VolumeCatalogInfo;
890 dev->ClearVolhdr();
891
892 /*
893 * Force re-read of label
894 */
895 dev->ClearLabeled();
896 dev->ClearRead();
897 dev->ClearAppend();
898 dev->label_type = B_BAREOS_LABEL;
899 VolumeName[0] = 0;
900
901 if (dev->IsOpen() && (!dev->IsTape() || !dev->HasCap(CAP_ALWAYSOPEN))) {
902 dev->close(dcr);
903 }
904
905 /*
906 * If we have not closed the device, then at least rewind the tape
907 */
908 if (dev->IsOpen()) { dev->OfflineOrRewind(); }
909 Dmsg0(190, "ReleaseVolume\n");
910 }
911
912 /**
913 * Insanity check
914 *
915 * Check to see if the tape position as defined by the OS is
916 * the same as our concept. If it is not,
917 * it means the user has probably manually rewound the tape.
918 * Note, we check only if num_writers == 0, but this code will
919 * also work fine for any number of writers. If num_writers > 0,
920 * we probably should cancel all jobs using this device, or
921 * perhaps even abort the SD, or at a minimum, mark the tape
922 * in error. Another strategy with num_writers == 0, would be
923 * to rewind the tape and do a new eod() request.
924 */
IsTapePositionOk()925 bool DeviceControlRecord::IsTapePositionOk()
926 {
927 if (dev->IsTape() && dev->num_writers == 0) {
928 int32_t file = dev->GetOsTapeFile();
929 if (file >= 0 && file != (int32_t)dev->GetFile()) {
930 Jmsg(jcr, M_ERROR, 0,
931 _("Invalid tape position on volume \"%s\""
932 " on device %s. Expected %d, got %d\n"),
933 dev->VolHdr.VolumeName, dev->print_name(), dev->GetFile(), file);
934 /*
935 * If the current file is greater than zero, it means we probably
936 * have some bad count of EOF marks, so mark tape in error. Otherwise
937 * the operator might have moved the tape, so we just release it
938 * and try again.
939 */
940 if (file > 0) { MarkVolumeInError(); }
941 ReleaseVolume();
942 return false;
943 }
944 }
945 return true;
946 }
947
948 /**
949 * If we are reading, we come here at the end of the tape
950 * and see if there are more volumes to be mounted.
951 */
MountNextReadVolume(DeviceControlRecord * dcr)952 bool MountNextReadVolume(DeviceControlRecord* dcr)
953 {
954 Device* dev = dcr->dev;
955 JobControlRecord* jcr = dcr->jcr;
956 Dmsg2(90, "NumReadVolumes=%d CurReadVolume=%d\n", jcr->impl->NumReadVolumes,
957 jcr->impl->CurReadVolume);
958
959 VolumeUnused(dcr); /* release current volume */
960 /*
961 * End Of Tape -- mount next Volume (if another specified)
962 */
963 if (jcr->impl->NumReadVolumes > 1 &&
964 jcr->impl->CurReadVolume < jcr->impl->NumReadVolumes) {
965 dev->Lock();
966 dev->close(dcr);
967 dev->SetRead();
968 dcr->SetReserved();
969 dev->Unlock();
970 if (!AcquireDeviceForRead(dcr)) {
971 Jmsg2(jcr, M_FATAL, 0, _("Cannot open Dev=%s, Vol=%s\n"),
972 dev->print_name(), dcr->VolumeName);
973 return false;
974 }
975 return true; /* next volume mounted */
976 }
977 Dmsg0(90, "End of Device reached.\n");
978 return false;
979 }
980
981 } /* namespace storagedaemon */
982