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