]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/mount.c
ebl Add sanity checks for VolWriteTime and VolReadTime
[bacula/bacula] / bacula / src / stored / mount.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2002-2008 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
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    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *
30  *  Routines for handling mounting tapes for reading and for
31  *    writing.
32  *
33  *   Kern Sibbald, August MMII
34  *
35  *   Version $Id$
36  */
37
38 #include "bacula.h"                   /* pull in global headers */
39 #include "stored.h"                   /* pull in Storage Deamon headers */
40
41 static void mark_volume_not_inchanger(DCR *dcr);
42 static int try_autolabel(DCR *dcr, bool opened);
43 static bool is_eod_valid(DCR *dcr);
44
45 enum {
46    try_next_vol = 1,
47    try_read_vol,
48    try_error,
49    try_default
50 };
51
52 /*
53  * If release is set, we rewind the current volume,
54  * which we no longer want, and ask the user (console)
55  * to mount the next volume.
56  *
57  *  Continue trying until we get it, and then ensure
58  *  that we can write on it.
59  *
60  * This routine returns a 0 only if it is REALLY
61  *  impossible to get the requested Volume.
62  *
63  */
64 bool DCR::mount_next_write_volume()
65 {
66    int retry = 0;
67    bool ask = false, recycle, autochanger;
68    int vol_label_status;
69    int mode;
70    DCR *dcr = this;
71
72    Dmsg2(150, "Enter mount_next_volume(release=%d) dev=%s\n", unload_device,
73       dev->print_name());
74
75    init_device_wait_timers(dcr);
76    lock_volumes();
77    
78    /*
79     * Attempt to mount the next volume. If something non-fatal goes
80     *  wrong, we come back here to re-try (new op messages, re-read
81     *  Volume, ...)
82     */
83 mount_next_vol:
84    Dmsg1(150, "mount_next_vol retry=%d\n", retry);
85    /* Ignore retry if this is poll request */
86    if (!dev->poll && retry++ > 4) {
87       /* Last ditch effort before giving up, force operator to respond */
88       VolCatInfo.Slot = 0;
89       if (!dir_ask_sysop_to_mount_volume(dcr, ST_APPEND)) {
90          Jmsg(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
91               dev->print_name());
92          goto bail_out;
93       }
94    }
95    if (job_canceled(jcr)) {
96       Jmsg(jcr, M_FATAL, 0, _("Job %d canceled.\n"), jcr->JobId);
97       goto bail_out;
98    }
99    recycle = false;
100    if (unload_device) {
101       Dmsg0(150, "mount_next_volume release=1\n");
102       release_volume(dcr);
103       unload_autochanger(dcr, -1);
104       unload_device = false;
105       ask = true;                     /* ask operator to mount tape */
106    }
107
108    /*
109     * Get Director's idea of what tape we should have mounted.
110     *    in dcr->VolCatInfo
111     */
112    Dmsg0(200, "Before dir_find_next_appendable_volume.\n");
113    while (!dir_find_next_appendable_volume(dcr)) {
114       Dmsg0(200, "not dir_find_next\n");
115       if (!dir_ask_sysop_to_create_appendable_volume(dcr)) {
116          goto bail_out;
117        }
118        Dmsg0(200, "Again dir_find_next_append...\n");
119    }
120    if (job_canceled(jcr)) {
121       goto bail_out;
122    }
123    Dmsg3(150, "After find_next_append. Vol=%s Slot=%d Parts=%d\n",
124          VolCatInfo.VolCatName, VolCatInfo.Slot, VolCatInfo.VolCatParts);
125    
126    /*
127     * Get next volume and ready it for append
128     * This code ensures that the device is ready for
129     * writing. We start from the assumption that there
130     * may not be a tape mounted.
131     *
132     * If the device is a file, we create the output
133     * file. If it is a tape, we check the volume name
134     * and move the tape to the end of data.
135     *
136     */
137    if (swap_dev) {
138       dev->vol = swap_dev->vol;      /* take its volume */
139       swap_dev->vol = NULL;
140       unload_dev(dcr, swap_dev);
141       swap_dev = NULL;
142    }
143    if (autoload_device(dcr, 1, NULL) > 0) {
144       autochanger = true;
145       ask = false;
146    } else {
147       autochanger = false;
148       VolCatInfo.Slot = 0;
149    }
150    Dmsg1(200, "autoload_dev returns %d\n", autochanger);
151    /*
152     * If we autochanged to correct Volume or (we have not just
153     *   released the Volume AND we can automount) we go ahead
154     *   and read the label. If there is no tape in the drive,
155     *   we will fail, recurse and ask the operator the next time.
156     */
157    if (!unload_device && dev->is_tape() && dev->has_cap(CAP_AUTOMOUNT)) {
158       Dmsg0(150, "(1)Ask=0\n");
159       ask = false;                 /* don't ask SYSOP this time */
160    }
161    /* Don't ask if not removable */
162    if (!dev->is_removable()) {
163       Dmsg0(150, "(2)Ask=0\n");
164       ask = false;
165    }
166    Dmsg2(150, "Ask=%d autochanger=%d\n", ask, autochanger);
167    unload_device = true;     /* release next time if we "recurse" */
168
169    if (ask && !dir_ask_sysop_to_mount_volume(dcr, ST_APPEND)) {
170       Dmsg0(150, "Error return ask_sysop ...\n");
171       goto bail_out;          /* error return */
172    }
173    if (job_canceled(jcr)) {
174       goto bail_out;
175    }
176    Dmsg3(150, "want vol=%s devvol=%s dev=%s\n", VolumeName, 
177       dev->VolHdr.VolumeName, dev->print_name());
178
179    if (dev->poll && dev->has_cap(CAP_CLOSEONPOLL)) {
180       dev->close();
181    }
182
183    /* Ensure the device is open */
184    if (dev->has_cap(CAP_STREAM)) {
185       mode = OPEN_WRITE_ONLY;
186    } else {
187       mode = OPEN_READ_WRITE;
188    }
189    /* Try autolabel if enabled */
190    if (dev->open(dcr, mode) < 0) {
191       try_autolabel(dcr, false);      /* try to create a new volume label */
192    }
193    while (dev->open(dcr, mode) < 0) {
194       Dmsg1(150, "open_device failed: ERR=%s\n", dev->bstrerror());
195       if ((dev->is_file() && dev->is_removable()) || dev->is_dvd()) {
196          bool ok = true;
197          Dmsg0(150, "call scan_dir_for_vol\n");
198          if (dev->is_dvd()) {
199             if (!dev->mount(0)) {
200                ok = false;
201             }
202          }
203          if (ok && dev->scan_dir_for_volume(dcr)) {
204             if (dev->open(dcr, mode) >= 0) {
205                break;                    /* got a valid volume */
206             }
207          }
208          if (ok && dev->is_dvd()) {
209             dev->unmount(0);
210          }
211       }
212       if (try_autolabel(dcr, false) == try_read_vol) {
213          break;                       /* created a new volume label */
214       }
215       /* If DVD, ignore the error, very often you cannot open the device
216        * (when there is no DVD, or when the one inserted is a wrong one) */
217       if (dev->poll || dev->is_dvd() || dev->is_removable()) {
218          goto mount_next_vol;
219       } else {
220          Jmsg(jcr, M_ERROR, 0, _("Could not open device %s: ERR=%s\n"),
221             dev->print_name(), dev->print_errmsg());
222          goto bail_out;
223       }
224    }
225
226    /*
227     * Now make sure we have the right tape mounted
228     */
229 read_volume:
230    /*
231     * If we are writing to a stream device, ASSUME the volume label
232     *  is correct.
233     */
234    if (dev->has_cap(CAP_STREAM)) {
235       vol_label_status = VOL_OK;
236       create_volume_label(dev, VolumeName, "Default", false /* not DVD */);
237       dev->VolHdr.LabelType = PRE_LABEL;
238    } else {
239       vol_label_status = read_dev_volume_label(dcr);
240    }
241    if (job_canceled(jcr)) {
242       goto bail_out;
243    }
244
245    Dmsg2(150, "Want dirVol=%s dirStat=%s\n", VolumeName,
246       VolCatInfo.VolCatStatus);
247    /*
248     * At this point, dev->VolCatInfo has what is in the drive, if anything,
249     *          and   dcr->VolCatInfo has what the Director wants.
250     */
251    switch (vol_label_status) {
252    case VOL_OK:
253       Dmsg1(150, "Vol OK name=%s\n", VolumeName);
254       dev->VolCatInfo = VolCatInfo;       /* structure assignment */
255       recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0;
256       break;                    /* got a Volume */
257    case VOL_NAME_ERROR:
258       VOLUME_CAT_INFO dcrVolCatInfo, devVolCatInfo;
259       char VolumeName[MAX_NAME_LENGTH];
260
261       /* If not removable, Volume is broken */
262       if (!dev->is_removable()) {
263          Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
264             VolumeName, dev->print_name());
265          dcr->mark_volume_in_error();
266          goto mount_next_vol;
267       }
268
269       Dmsg1(150, "Vol NAME Error Name=%s\n", VolumeName);
270       /* If polling and got a previous bad name, ignore it */
271       if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolumeName) == 0) {
272          ask = true;
273          Dmsg1(200, "Vol Name error supress due to poll. Name=%s\n", VolumeName);
274          goto mount_next_vol;
275       }
276       /*
277        * OK, we got a different volume mounted. First save the
278        *  requested Volume info (dcr) structure, then query if
279        *  this volume is really OK. If not, put back the desired
280        *  volume name, mark it not in changer and continue.
281        */
282       dcrVolCatInfo = VolCatInfo;      /* structure assignment */
283       devVolCatInfo = dev->VolCatInfo;      /* structure assignment */
284       /* Check if this is a valid Volume in the pool */
285       bstrncpy(VolumeName, VolumeName, sizeof(VolumeName));
286       bstrncpy(VolumeName, dev->VolHdr.VolumeName, sizeof(VolumeName));
287       if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) {
288          POOL_MEM vol_info_msg;
289          pm_strcpy(vol_info_msg, jcr->dir_bsock->msg);  /* save error message */
290          /* Restore desired volume name, note device info out of sync */
291          /* This gets the info regardless of the Pool */
292          bstrncpy(VolumeName, dev->VolHdr.VolumeName, sizeof(VolumeName));
293          if (autochanger && !dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
294             /*
295              * If we get here, we know we cannot write on the Volume,
296              *  and we know that we cannot read it either, so it 
297              *  is not in the autochanger.
298              */
299             mark_volume_not_inchanger(dcr);
300          }
301          dev->VolCatInfo = devVolCatInfo;    /* structure assignment */
302          bstrncpy(dev->BadVolName, dev->VolHdr.VolumeName, sizeof(dev->BadVolName));
303          Jmsg(jcr, M_WARNING, 0, _("Director wanted Volume \"%s\".\n"
304               "    Current Volume \"%s\" not acceptable because:\n"
305               "    %s"),
306              dcrVolCatInfo.VolCatName, dev->VolHdr.VolumeName,
307              vol_info_msg.c_str());
308          ask = true;
309          /* Restore saved DCR before continuing */
310          bstrncpy(VolumeName, VolumeName, sizeof(VolumeName));
311          VolCatInfo = dcrVolCatInfo;  /* structure assignment */
312          goto mount_next_vol;
313       }
314       /*
315        * This was not the volume we expected, but it is OK with
316        * the Director, so use it.
317        */
318       Dmsg1(150, "want new name=%s\n", VolumeName);
319       dev->VolCatInfo = VolCatInfo;   /* structure assignment */
320       recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0;
321       break;                /* got a Volume */
322    /*
323     * At this point, we assume we have a blank tape mounted.
324     */
325    case VOL_IO_ERROR:
326       if (dev->is_dvd()) {
327          Jmsg(jcr, M_FATAL, 0, "%s", jcr->errmsg);
328          dcr->mark_volume_in_error();
329          goto bail_out;       /* we could not write on DVD */
330       }
331       /* Fall through wanted */
332    case VOL_NO_LABEL:
333       switch (try_autolabel(dcr, true)) {
334       case try_next_vol:
335          goto mount_next_vol;
336       case try_read_vol:
337          goto read_volume;
338       case try_error:
339          goto bail_out;
340       case try_default:
341          break;
342       }
343
344       /* NOTE! Fall-through wanted. */
345    case VOL_NO_MEDIA:
346    default:
347       Dmsg0(200, "VOL_NO_MEDIA or default.\n");
348       /* Send error message */
349       if (!dev->poll) {
350       } else {
351          Dmsg1(200, "Msg suppressed by poll: %s\n", jcr->errmsg);
352       }
353       ask = true;
354       /* Needed, so the medium can be changed */
355       if (dev->requires_mount()) {
356          dev->close();
357       }
358       goto mount_next_vol;
359    }
360
361    /*
362     * See if we have a fresh tape or a tape with data.
363     *
364     * Note, if the LabelType is PRE_LABEL, it was labeled
365     *  but never written. If so, rewrite the label but set as
366     *  VOL_LABEL.  We rewind and return the label (reconstructed)
367     *  in the block so that in the case of a new tape, data can
368     *  be appended just after the block label.  If we are writing
369     *  a second volume, the calling routine will write the label
370     *  before writing the overflow block.
371     *
372     *  If the tape is marked as Recycle, we rewrite the label.
373     */
374    if (dev->VolHdr.LabelType == PRE_LABEL || recycle) {
375       if (!rewrite_volume_label(dcr, recycle)) {
376          dcr->mark_volume_in_error();
377          goto mount_next_vol;
378       }
379    } else {
380       /*
381        * OK, at this point, we have a valid Bacula label, but
382        * we need to position to the end of the volume, since we are
383        * just now putting it into append mode.
384        */
385       Dmsg0(200, "Device previously written, moving to end of data\n");
386       Jmsg(jcr, M_INFO, 0, _("Volume \"%s\" previously written, moving to end of data.\n"),
387          VolumeName);
388
389       if (!dev->eod(dcr)) {
390          Jmsg(jcr, M_ERROR, 0, _("Unable to position to end of data on device %s: ERR=%s\n"),
391             dev->print_name(), dev->bstrerror());
392          dcr->mark_volume_in_error();
393          goto mount_next_vol;
394       }
395       if (!is_eod_valid(dcr)) {
396          goto mount_next_vol;
397       }
398
399       dev->VolCatInfo.VolCatMounts++;      /* Update mounts */
400       Dmsg1(150, "update volinfo mounts=%d\n", dev->VolCatInfo.VolCatMounts);
401       if (!dir_update_volume_info(dcr, false, false)) {
402          goto bail_out;
403       }
404       
405       /* Return an empty block */
406       empty_block(block);             /* we used it for reading so set for write */
407    }
408    dev->set_append();
409    Dmsg1(150, "set APPEND, normal return from mount_next_write_volume. dev=%s\n",
410       dev->print_name());
411
412    unlock_volumes();
413    return true;
414
415 bail_out:
416    unlock_volumes();
417    return false;
418 }
419
420
421 /*
422  * Check if the current position on the volume corresponds to
423  *  what is in the catalog.
424  */
425 static bool is_eod_valid(DCR *dcr)
426 {
427    DEVICE *dev = dcr->dev;
428    JCR *jcr = dcr->jcr;
429
430    if (dev->is_dvd()) {
431       char ed1[50], ed2[50];
432       if (dev->VolCatInfo.VolCatBytes == dev->part_start + dev->part_size) {
433          Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\""
434               " part=%d size=%s\n"), dcr->VolumeName, 
435               dev->part, edit_uint64(dev->VolCatInfo.VolCatBytes,ed1));
436       } else {
437          Jmsg(jcr, M_ERROR, 0, _("Bacula cannot write on DVD Volume \"%s\" because: "
438               "The sizes do not match! Volume=%s Catalog=%s\n"),
439               dcr->VolumeName,
440               edit_uint64(dev->part_start + dev->part_size, ed1),
441               edit_uint64(dev->VolCatInfo.VolCatBytes, ed2));
442          dcr->mark_volume_in_error();
443          return false;
444       }
445    } else if (dev->is_tape()) {
446       /*
447        * Check if we are positioned on the tape at the same place
448        * that the database says we should be.
449        */
450       if (dev->VolCatInfo.VolCatFiles == dev->get_file()) {
451          Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\" at file=%d.\n"),
452               dcr->VolumeName, dev->get_file());
453       } else {
454          Jmsg(jcr, M_ERROR, 0, _("Bacula cannot write on tape Volume \"%s\" because:\n"
455               "The number of files mismatch! Volume=%u Catalog=%u\n"),
456               dcr->VolumeName, dev->get_file(), dev->VolCatInfo.VolCatFiles);
457          dcr->mark_volume_in_error();
458          return false;
459       }
460    } else if (dev->is_file()) {
461       char ed1[50], ed2[50];
462       boffset_t pos;
463       pos = dev->lseek(dcr, (boffset_t)0, SEEK_END);
464       if (dev->VolCatInfo.VolCatBytes == (uint64_t)pos) {
465          Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\""
466               " size=%s\n"), dcr->VolumeName, 
467               edit_uint64(dev->VolCatInfo.VolCatBytes, ed1));
468       } else {
469          Jmsg(jcr, M_ERROR, 0, _("Bacula cannot write on disk Volume \"%s\" because: "
470               "The sizes do not match! Volume=%s Catalog=%s\n"),
471               dcr->VolumeName,
472               edit_uint64(pos, ed1),
473               edit_uint64(dev->VolCatInfo.VolCatBytes, ed2));
474          dcr->mark_volume_in_error();
475          return false;
476       }
477    }
478    return true;
479 }
480
481
482 /*
483  * If permitted, we label the device, make sure we can do
484  *   it by checking that the VolCatBytes is zero => not labeled,
485  *   once the Volume is labeled we don't want to label another
486  *   blank tape with the same name.  For disk, we go ahead and
487  *   label it anyway, because the OS insures that there is only
488  *   one Volume with that name.
489  * As noted above, at this point dcr->VolCatInfo has what
490  *   the Director wants and dev->VolCatInfo has info on the
491  *   previous tape (or nothing).
492  *
493  * Return codes are:
494  *   try_next_vol        label failed, look for another volume
495  *   try_read_vol        labeled volume, now re-read the label
496  *   try_error           hard error (catalog update)
497  *   try_default         I couldn't do anything
498  */
499 static int try_autolabel(DCR *dcr, bool opened)
500 {
501    DEVICE *dev = dcr->dev;
502
503    if (dev->poll && !dev->is_tape()) {
504       return try_default;       /* if polling, don't try to create new labels */
505    }
506    /* For a tape require it to be opened and read before labeling */
507    if (!opened && dev->is_tape()) {
508       return try_default;
509    }
510    if (dev->has_cap(CAP_LABEL) && (dcr->VolCatInfo.VolCatBytes == 0 ||
511          (!dev->is_tape() && strcmp(dcr->VolCatInfo.VolCatStatus,
512                                 "Recycle") == 0))) {
513       Dmsg0(150, "Create volume label\n");
514       /* Create a new Volume label and write it to the device */
515       if (!write_new_volume_label_to_dev(dcr, dcr->VolumeName,
516              dcr->pool_name, false, /* no relabel */ false /* defer DVD label */)) {
517          Dmsg0(150, "!write_vol_label\n");
518          if (opened) { 
519             dcr->mark_volume_in_error();
520          }
521          return try_next_vol;
522       }
523       Dmsg0(150, "dir_update_vol_info. Set Append\n");
524       /* Copy Director's info into the device info */
525       dev->VolCatInfo = dcr->VolCatInfo;    /* structure assignment */
526       if (!dir_update_volume_info(dcr, true, true)) {  /* indicate tape labeled */
527          return try_error;
528       }
529       Jmsg(dcr->jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"),
530          dcr->VolumeName, dev->print_name());
531       return try_read_vol;   /* read label we just wrote */
532    }
533    if (!dev->has_cap(CAP_LABEL) && dcr->VolCatInfo.VolCatBytes == 0) {
534       Jmsg(dcr->jcr, M_WARNING, 0, _("Device %s not configured to autolabel Volumes.\n"), 
535          dev->print_name());
536    }
537    /* If not removable, Volume is broken */
538    if (!dev->is_removable()) {
539       Jmsg(dcr->jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
540          dcr->VolumeName, dev->print_name());
541       dcr->mark_volume_in_error();
542       return try_next_vol;
543    }
544    return try_default;
545 }
546
547
548 /*
549  * Mark volume in error in catalog
550  */
551 void DCR::mark_volume_in_error()
552 {
553    Jmsg(jcr, M_INFO, 0, _("Marking Volume \"%s\" in Error in Catalog.\n"),
554         VolumeName);
555    dev->VolCatInfo = VolCatInfo;     /* structure assignment */
556    bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus));
557    Dmsg0(150, "dir_update_vol_info. Set Error.\n");
558    dir_update_volume_info(this, false, false);
559    volume_unused(this);
560 }
561
562 /*
563  * The Volume is not in the correct slot, so mark this
564  *   Volume as not being in the Changer.
565  */
566 static void mark_volume_not_inchanger(DCR *dcr)
567 {
568    JCR *jcr = dcr->jcr;
569    DEVICE *dev = dcr->dev;
570    Jmsg(jcr, M_ERROR, 0, _("Autochanger Volume \"%s\" not found in slot %d.\n"
571 "    Setting InChanger to zero in catalog.\n"),
572         dcr->VolCatInfo.VolCatName, dcr->VolCatInfo.Slot);
573    dev->VolCatInfo = dcr->VolCatInfo;    /* structure assignment */
574    dcr->VolCatInfo.InChanger = false;
575    dev->VolCatInfo.InChanger = false;
576    Dmsg0(400, "update vol info in mount\n");
577    dir_update_volume_info(dcr, true, false);  /* set new status */
578 }
579
580 /*
581  * Either because we are going to hang a new volume, or because
582  *  of explicit user request, we release the current volume.
583  */
584 void release_volume(DCR *dcr)
585 {
586    JCR *jcr = dcr->jcr;
587    DEVICE *dev = dcr->dev;
588    if (dcr->WroteVol) {
589       Jmsg0(jcr, M_ERROR, 0, _("Hey!!!!! WroteVol non-zero !!!!!\n"));
590       Dmsg0(190, "Hey!!!!! WroteVol non-zero !!!!!\n");
591    }
592    /*
593     * First erase all memory of the current volume
594     */
595    free_volume(dev);
596    dev->block_num = dev->file = 0;
597    dev->EndBlock = dev->EndFile = 0;
598    memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo));
599 // memset(&dcr->VolCatInfo, 0, sizeof(dcr->VolCatInfo));
600    dev->clear_volhdr();
601    /* Force re-read of label */
602    dev->clear_labeled();
603    dev->clear_read();
604    dev->clear_append();
605    dev->label_type = B_BACULA_LABEL;
606 // dcr->VolumeName[0] = 0;
607
608    if (dev->is_open() && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
609       dev->close();
610    }
611
612    /* If we have not closed the device, then at least rewind the tape */
613    if (dev->is_open()) {
614       dev->offline_or_rewind();
615    }
616    Dmsg0(190, "release_volume\n");
617 }
618
619 /*
620  * If we are reading, we come here at the end of the tape
621  *  and see if there are more volumes to be mounted.
622  */
623 bool mount_next_read_volume(DCR *dcr)
624 {
625    DEVICE *dev = dcr->dev;
626    JCR *jcr = dcr->jcr;
627    Dmsg2(90, "NumReadVolumes=%d CurReadVolume=%d\n", jcr->NumReadVolumes, jcr->CurReadVolume);
628
629    volume_unused(dcr);                /* release current volume */
630    /*
631     * End Of Tape -- mount next Volume (if another specified)
632     */
633    if (jcr->NumReadVolumes > 1 && jcr->CurReadVolume < jcr->NumReadVolumes) {
634       dev->close();
635       if (!acquire_device_for_read(dcr)) {
636          Jmsg2(jcr, M_FATAL, 0, _("Cannot open Dev=%s, Vol=%s\n"), dev->print_name(),
637                dcr->VolumeName);
638          return false;
639       }
640       return true;                    /* next volume mounted */
641    }
642    Dmsg0(90, "End of Device reached.\n");
643    return false;
644 }