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