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