]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/acquire.c
9528f786c562748af04b009f7421e88501bca29f
[bacula/bacula] / bacula / src / stored / acquire.c
1 /*
2  *  Routines to acquire and release a device for read/write
3  *
4  *   Kern Sibbald, August MMII
5  *
6  *   Version $Id$
7  */
8 /*
9    Copyright (C) 2002-2006 Kern Sibbald
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License
13    version 2 as amended with additional clauses defined in the
14    file LICENSE in the main source directory.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
19    the file LICENSE for additional details.
20
21  */
22
23 #include "bacula.h"                   /* pull in global headers */
24 #include "stored.h"                   /* pull in Storage Deamon headers */
25
26 /* Forward referenced functions */
27 static void detach_dcr_from_dev(DCR *dcr);
28
29
30 /*********************************************************************
31  * Acquire device for reading. 
32  *  The drive should have previously been reserved by calling 
33  *  reserve_device_for_read(). We read the Volume label from the block and
34  *  leave the block pointers just after the label.
35  *
36  *  Returns: NULL if failed for any reason
37  *           dcr  if successful
38  */
39 bool acquire_device_for_read(DCR *dcr)
40 {
41    DEVICE *dev = dcr->dev;
42    JCR *jcr = dcr->jcr;
43    bool ok = false;
44    bool tape_previously_mounted;
45    bool tape_initially_mounted;
46    VOL_LIST *vol;
47    bool try_autochanger = true;
48    int i;
49    int vol_label_status;
50    
51    Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr);
52    dev->block(BST_DOING_ACQUIRE);
53
54    if (dev->num_writers > 0) {
55       Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"), 
56          dev->num_writers, jcr->JobId);
57       goto get_out;
58    }
59
60    /* Find next Volume, if any */
61    vol = jcr->VolList;
62    if (!vol) {
63       Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job %d canceled.\n"), jcr->JobId);
64       goto get_out;
65    }
66    jcr->CurVolume++;
67    for (i=1; i<jcr->CurVolume; i++) {
68       vol = vol->next;
69    }
70    if (!vol) {
71       goto get_out;                   /* should not happen */   
72    }
73    bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
74    bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
75    dcr->VolCatInfo.Slot = vol->Slot;
76     
77    /*
78     * If the MediaType requested for this volume is not the
79     *  same as the current drive, we attempt to find the same
80     *  device that was used to write the orginal volume.  If
81     *  found, we switch to using that device.
82     */
83    Dmsg2(100, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
84    if (dcr->media_type[0] && strcmp(dcr->media_type, dev->device->media_type) != 0) {
85       RCTX rctx;
86       DIRSTORE *store;
87       int stat;
88       DCR *dcr_save = jcr->dcr;
89
90       jcr->dcr = NULL;
91       memset(&rctx, 0, sizeof(RCTX));
92       rctx.jcr = jcr;
93       jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
94       rctx.any_drive = true;
95       rctx.device_name = vol->device;
96       store = new DIRSTORE;
97       memset(store, 0, sizeof(DIRSTORE));
98       store->name[0] = 0; /* No dir name */
99       bstrncpy(store->media_type, vol->MediaType, sizeof(store->media_type));
100       bstrncpy(store->pool_name, dcr->pool_name, sizeof(store->pool_name));
101       bstrncpy(store->pool_type, dcr->pool_type, sizeof(store->pool_type));
102       store->append = false;
103       rctx.store = store;
104       
105       /*
106        * Note, if search_for_device() succeeds, we get a new_dcr,
107        *  which we do not use except for the dev info.
108        */
109       stat = search_res_for_device(rctx);
110       release_msgs(jcr);              /* release queued messages */
111       if (stat == 1) {
112          DCR *new_dcr = jcr->read_dcr;
113          dev->unblock();
114          detach_dcr_from_dev(dcr);    /* release old device */
115          /* Copy important info from the new dcr */
116          dev = dcr->dev = new_dcr->dev; 
117          jcr->read_dcr = dcr; 
118          dcr->device = new_dcr->device;
119          dcr->max_job_spool_size = dcr->device->max_job_spool_size;
120          if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
121             dev->attached_dcrs->append(dcr);  /* attach dcr to device */
122          }
123          new_dcr->VolumeName[0] = 0;
124          free_dcr(new_dcr);
125          dev->block(BST_DOING_ACQUIRE); 
126          Jmsg(jcr, M_INFO, 0, _("Media Type change.  New device %s chosen.\n"),
127             dev->print_name());
128          bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
129          bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
130          dcr->VolCatInfo.Slot = vol->Slot;
131          bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name));
132          bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type));
133       } else if (stat == 0) {   /* device busy */
134          Dmsg1(000, "Device %s is busy.\n", vol->device);
135       } else {
136          /* error */
137          Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
138             vol->VolumeName);
139          jcr->dcr = dcr_save;
140          goto get_out;
141       }
142       jcr->dcr = dcr_save;
143    }
144
145
146    init_device_wait_timers(dcr);
147
148    tape_previously_mounted = dev->can_read() || dev->can_append() ||
149                              dev->is_labeled();
150    tape_initially_mounted = tape_previously_mounted;
151
152
153    /* Volume info is always needed because of VolParts */
154    Dmsg0(200, "dir_get_volume_info\n");
155    if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
156       Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
157    }
158    
159    for (i=0; i<5; i++) {
160       dev->clear_labeled();              /* force reread of label */
161       if (job_canceled(jcr)) {
162          Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
163          goto get_out;                /* error return */
164       }
165       /*
166        * This code ensures that the device is ready for
167        * reading. If it is a file, it opens it.
168        * If it is a tape, it checks the volume name
169        */
170       Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
171       if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
172          if (dev->dev_errno == EIO) {   /* no tape loaded */
173            Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed (EIO): ERR=%s\n"),
174                  dev->print_name(), dcr->VolumeName, dev->bstrerror());
175             goto default_path;
176          }
177          
178          Jmsg3(jcr, M_FATAL, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"),
179              dev->print_name(), dcr->VolumeName, dev->bstrerror());
180          goto get_out;
181       }
182       Dmsg1(100, "opened dev %s OK\n", dev->print_name());
183       
184       /* Read Volume Label */
185       
186       Dmsg0(200, "calling read-vol-label\n");
187       vol_label_status = read_dev_volume_label(dcr);
188       switch (vol_label_status) {
189       case VOL_OK:
190          ok = true;
191          memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
192          break;                    /* got it */
193       case VOL_IO_ERROR:
194          /*
195           * Send error message generated by read_dev_volume_label()
196           *  only we really had a tape mounted. This supresses superfluous
197           *  error messages when nothing is mounted.
198           */
199          if (tape_previously_mounted) {
200             Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
201          }
202          goto default_path;
203       case VOL_NAME_ERROR:
204          if (tape_initially_mounted) {
205             tape_initially_mounted = false;
206             goto default_path;
207          }
208          /* Fall through */
209       default:
210          Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
211 default_path:
212          tape_previously_mounted = true;
213          
214          /*
215           * If the device requires mount, close it, so the device can be ejected.
216           */
217          if (dev->requires_mount()) {
218             dev->close();
219          }
220          
221          /* Call autochanger only once unless ask_sysop called */
222          if (try_autochanger) {
223             int stat;
224             Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
225                dcr->VolumeName, dcr->VolCatInfo.Slot);
226             stat = autoload_device(dcr, 0, NULL);
227             if (stat > 0) {
228                try_autochanger = false;
229                continue;              /* try reading volume mounted */
230             }
231          }
232          
233          /* Mount a specific volume and no other */
234          Dmsg0(200, "calling dir_ask_sysop\n");
235          if (!dir_ask_sysop_to_mount_volume(dcr)) {
236             goto get_out;             /* error return */
237          }
238          try_autochanger = true;      /* permit using autochanger again */
239          continue;                    /* try reading again */
240       } /* end switch */
241       break;
242    } /* end for loop */
243    if (!ok) {
244       Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
245             dev->print_name());
246       goto get_out;
247    }
248
249    dev->clear_append();
250    dev->set_read();
251    set_jcr_job_status(jcr, JS_Running);
252    dir_send_job_status(jcr);
253    Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
254       dcr->VolumeName, dev->print_name());
255
256 get_out:
257    P(dev->mutex);
258    if (dcr->reserved_device) {
259       dev->reserved_device--;
260       Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
261       dcr->reserved_device = false;
262    }
263    V(dev->mutex);
264    dev->unblock();
265    Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr);
266    return ok;
267 }
268
269
270 /*
271  * Acquire device for writing. We permit multiple writers.
272  *  If this is the first one, we read the label.
273  *
274  *  Returns: NULL if failed for any reason
275  *           dcr if successful.
276  *   Note, normally reserve_device_for_append() is called
277  *   before this routine.
278  */
279 DCR *acquire_device_for_append(DCR *dcr)
280 {
281    bool release = false;
282    bool recycle = false;
283    bool do_mount = false;
284    DEVICE *dev = dcr->dev;
285    JCR *jcr = dcr->jcr;
286
287    init_device_wait_timers(dcr);
288
289    dev->block(BST_DOING_ACQUIRE);
290    Dmsg1(190, "acquire_append device is %s\n", dev->is_tape()?"tape":
291         (dev->is_dvd()?"DVD":"disk"));
292
293    /*
294     * With the reservation system, this should not happen
295     */
296    if (dev->can_read()) {
297       Jmsg1(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev->print_name());
298       Dmsg1(200, "Device %s is busy reading.\n", dev->print_name());
299       goto get_out;
300    }
301
302    if (dev->can_append()) {
303       Dmsg0(190, "device already in append.\n");
304       /*
305        * Device already in append mode
306        *
307        * Check if we have the right Volume mounted
308        *   OK if current volume info OK
309        *   OK if next volume matches current volume
310        *   otherwise mount desired volume obtained from
311        *    dir_find_next_appendable_volume
312        *  dev->VolHdr.VolumeName is what is in the drive
313        *  dcr->VolumeName is what we pass into the routines, or
314        *    get back from the subroutines.
315        */
316       bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
317       if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
318           !(dir_find_next_appendable_volume(dcr) &&
319             strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
320          Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName,
321             dcr->VolumeName);
322          /* Release volume reserved by dir_find_next_appendable_volume() */
323          if (dcr->VolumeName[0]) {
324             free_unused_volume(dcr);
325          }
326          if (dev->num_writers != 0) {
327             Jmsg3(jcr, M_FATAL, 0, _("Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n"), 
328                  dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
329             Dmsg3(200, "Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n",  
330                  dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
331             goto get_out;
332          }
333          /* Wrong tape mounted, release it, then fall through to get correct one */
334          Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
335          release = true;
336          do_mount = true;
337       } else {
338          /*
339           * At this point, the correct tape is already mounted, so
340           *   we do not need to do mount_next_write_volume(), unless
341           *   we need to recycle the tape.
342           */
343           recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
344           Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
345           if (recycle && dev->num_writers != 0) {
346              Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
347                   " on device %s because it is in use by another job.\n"),
348                   dev->VolHdr.VolumeName, dev->print_name());
349              goto get_out;
350           }
351           if (dev->num_writers == 0) {
352              memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
353           }
354       }
355    } else {
356       /* Not already in append mode, so mount the device */
357       Dmsg0(190, "Not in append mode, try mount.\n");
358       ASSERT(dev->num_writers == 0);
359       do_mount = true;
360    }
361
362    if (do_mount || recycle) {
363       Dmsg0(190, "Do mount_next_write_vol\n");
364       bool mounted = mount_next_write_volume(dcr, release);
365       if (!mounted) {
366          if (!job_canceled(jcr)) {
367             /* Reduce "noise" -- don't print if job canceled */
368             Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
369                dev->print_name());
370             Dmsg1(200, "Could not ready device %s for append.\n", 
371                dev->print_name());
372          }
373          goto get_out;
374       }
375    }
376
377    dev->num_writers++;                /* we are now a writer */
378    if (jcr->NumVolumes == 0) {
379       jcr->NumVolumes = 1;
380    }
381    P(dev->mutex);
382    if (dcr->reserved_device) {
383       dev->reserved_device--;
384       Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
385       dcr->reserved_device = false;
386    }
387    V(dev->mutex);
388    dev->unblock();
389    return dcr;
390
391 /*
392  * Error return
393  */
394 get_out:
395    P(dev->mutex);
396    if (dcr->reserved_device) {
397       dev->reserved_device--;
398       Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
399       dcr->reserved_device = false;
400    }
401    V(dev->mutex);
402    dev->unblock();
403    return NULL;
404 }
405
406
407 /*
408  * This job is done, so release the device. From a Unix standpoint,
409  *  the device remains open.
410  *
411  */
412 bool release_device(DCR *dcr)
413 {
414    JCR *jcr = dcr->jcr;
415    DEVICE *dev = dcr->dev;
416    bool ok = true;
417
418    lock_device(dev);
419    Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
420
421    /* if device is reserved, job never started, so release the reserve here */
422    if (dcr->reserved_device) {
423       dev->reserved_device--;
424       Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
425       dcr->reserved_device = false;
426    }
427
428    if (dev->can_read()) {
429       dev->clear_read();              /* clear read bit */
430
431       /******FIXME**** send read volume usage statistics to director */
432
433    } else if (dev->num_writers > 0) {
434       /* 
435        * Note if WEOT is set, we are at the end of the tape
436        *   and may not be positioned correctly, so the
437        *   job_media_record and update_vol_info have already been
438        *   done, which means we skip them here.
439        */
440       dev->num_writers--;
441       Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
442       if (dev->is_labeled()) {
443          Dmsg0(100, "dir_create_jobmedia_record. Release\n");
444          if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
445             Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
446                dcr->VolCatInfo.VolCatName, jcr->Job);
447          }
448          /* If no more writers, write an EOF */
449          if (!dev->num_writers && dev->can_write()) {
450             weof_dev(dev, 1);
451             write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
452          }
453          if (!dev->at_weot()) {
454             dev->VolCatInfo.VolCatFiles = dev->file;   /* set number of files */
455             dev->VolCatInfo.VolCatJobs++;              /* increment number of jobs */
456             /* Note! do volume update before close, which zaps VolCatInfo */
457             Dmsg0(100, "dir_update_vol_info. Release0\n");
458             dir_update_volume_info(dcr, false); /* send Volume info to Director */
459          }
460       }
461
462    } else {
463       /*                
464        * If we reach here, it is most likely because the job
465        *   has failed, since the device is not in read mode and
466        *   there are no writers. It was probably reserved.
467        */
468    }
469
470    /* If no writers, close if file or !CAP_ALWAYS_OPEN */
471    if (dev->num_writers == 0 && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
472       dev->close();
473    }
474
475    /* Fire off Alert command and include any output */
476    if (!job_canceled(jcr) && dcr->device->alert_command) {
477       POOLMEM *alert;
478       int status = 1;
479       BPIPE *bpipe;
480       char line[MAXSTRING];
481       alert = get_pool_memory(PM_FNAME);
482       alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
483       bpipe = open_bpipe(alert, 0, "r");
484       if (bpipe) {
485          while (fgets(line, sizeof(line), bpipe->rfd)) {
486             Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
487          }
488          status = close_bpipe(bpipe);
489       } else {
490          status = errno;
491       }
492       if (status != 0) {
493          berrno be;
494          Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
495               alert, be.strerror(status));
496       }
497
498       Dmsg1(400, "alert status=%d\n", status);
499       free_pool_memory(alert);
500    }
501    unlock_device(dev);
502    if (jcr->read_dcr == dcr) {
503       jcr->read_dcr = NULL;
504    }
505    if (jcr->dcr == dcr) {
506       jcr->dcr = NULL;
507    }
508    free_dcr(dcr);
509    return ok;
510 }
511
512 /*
513  * Create a new Device Control Record and attach
514  *   it to the device (if this is a real job).
515  */
516 DCR *new_dcr(JCR *jcr, DEVICE *dev)
517 {
518    DCR *dcr = (DCR *)malloc(sizeof(DCR));
519    memset(dcr, 0, sizeof(DCR));
520    dcr->jcr = jcr;
521    if (dev) {
522       dcr->dev = dev;
523       dcr->device = dev->device;
524       dcr->block = new_block(dev);
525       dcr->rec = new_record();
526       dcr->max_job_spool_size = dev->device->max_job_spool_size;
527       /* Attach this dcr only if dev is initialized */
528       if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
529          dev->attached_dcrs->append(dcr);  /* attach dcr to device */
530 //       jcr->dcrs->append(dcr);         /* put dcr in list for Job */
531       }
532    }
533    dcr->spool_fd = -1;
534    return dcr;
535 }
536
537 /*
538  * Search the dcrs list for the given dcr. If it is found,
539  *  as it should be, then remove it. Also zap the jcr pointer
540  *  to the dcr if it is the same one.
541  */
542 #ifdef needed
543 static void remove_dcr_from_dcrs(DCR *dcr)
544 {
545    JCR *jcr = dcr->jcr;
546    if (jcr->dcrs) {
547       int i = 0;
548       DCR *ldcr;
549       int num = jcr->dcrs->size();
550       for (i=0; i < num; i++) {
551          ldcr = (DCR *)jcr->dcrs->get(i);
552          if (ldcr == dcr) {
553             jcr->dcrs->remove(i);
554             if (jcr->dcr == dcr) {
555                jcr->dcr = NULL;
556             }
557          }
558       }
559    }
560 }
561 #endif
562
563 static void detach_dcr_from_dev(DCR *dcr)
564 {
565    DEVICE *dev = dcr->dev;
566
567    if (dcr->reserved_device) {
568       dcr->reserved_device = false;
569       lock_device(dev);
570       dev->reserved_device--;
571       Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
572       dcr->reserved_device = false;
573       /* If we set read mode in reserving, remove it */
574       if (dev->can_read()) {
575          dev->clear_read();
576       }
577       if (dev->num_writers < 0) {
578          Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
579          dev->num_writers = 0;
580       }
581       unlock_device(dev);
582    }
583
584    /* Detach this dcr only if the dev is initialized */
585    if (dcr->dev->fd != 0 && dcr->jcr && dcr->jcr->JobType != JT_SYSTEM) {
586       dcr->dev->attached_dcrs->remove(dcr);  /* detach dcr from device */
587 //    remove_dcr_from_dcrs(dcr);      /* remove dcr from jcr list */
588    }
589    free_unused_volume(dcr);           /* free unused vols attached to this dcr */
590    pthread_cond_broadcast(&dcr->dev->wait_next_vol);
591    pthread_cond_broadcast(&wait_device_release);
592 }
593
594 /*
595  * Free up all aspects of the given dcr -- i.e. dechain it,
596  *  release allocated memory, zap pointers, ...
597  */
598 void free_dcr(DCR *dcr)
599 {
600
601    detach_dcr_from_dev(dcr);
602
603    if (dcr->block) {
604       free_block(dcr->block);
605    }
606    if (dcr->rec) {
607       free_record(dcr->rec);
608    }
609    if (dcr->jcr) {
610       dcr->jcr->dcr = NULL;
611    }
612    free(dcr);
613 }