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