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