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