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