]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/acquire.c
- Apply Landon's patch for the TLS ANS1 API change.
[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-2005 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 /*
27  * Create a new Device Control Record and attach
28  *   it to the device (if this is a real job).
29  */
30 DCR *new_dcr(JCR *jcr, DEVICE *dev)
31 {
32    if (jcr && jcr->dcr) {
33       return jcr->dcr;
34    }
35    DCR *dcr = (DCR *)malloc(sizeof(DCR));
36    memset(dcr, 0, sizeof(DCR));
37    dcr->jcr = jcr;
38    if (dev) {
39       if (jcr) {
40          jcr->dcr = dcr;
41       }
42       dcr->dev = dev;
43       dcr->device = dev->device;
44       dcr->block = new_block(dev);
45       dcr->rec = new_record();
46       dcr->max_job_spool_size = dev->device->max_job_spool_size;
47       /* Attach this dcr only if dev is initialized */
48       if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
49          dev->attached_dcrs->append(dcr);  /* attach dcr to device */
50 //       jcr->dcrs->append(dcr);         /* put dcr in list for Job */
51       }
52    }
53    dcr->spool_fd = -1;
54    return dcr;
55 }
56
57 /*
58  * Search the dcrs list for the given dcr. If it is found,
59  *  as it should be, then remove it. Also zap the jcr pointer
60  *  to the dcr if it is the same one.
61  */
62 #ifdef needed
63 static void remove_dcr_from_dcrs(DCR *dcr)
64 {
65    JCR *jcr = dcr->jcr;
66    if (jcr->dcrs) {
67       int i = 0;
68       DCR *ldcr;
69       int num = jcr->dcrs->size();
70       for (i=0; i < num; i++) {
71          ldcr = (DCR *)jcr->dcrs->get(i);
72          if (ldcr == dcr) {
73             jcr->dcrs->remove(i);
74             if (jcr->dcr == dcr) {
75                jcr->dcr = NULL;
76             }
77          }
78       }
79    }
80 }
81 #endif
82
83 /*
84  * Free up all aspects of the given dcr -- i.e. dechain it,
85  *  release allocated memory, zap pointers, ...
86  */
87 void free_dcr(DCR *dcr)
88 {
89    JCR *jcr = dcr->jcr;
90    DEVICE *dev = dcr->dev;
91
92    if (dcr->reserved_device) {
93       lock_device(dev);
94       dev->reserved_device--;
95       Dmsg1(200, "Dec reserve=%d\n", dev->reserved_device);
96       dcr->reserved_device = false;
97       if (dev->num_writers < 0) {
98          Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
99          dev->num_writers = 0;
100       }
101       unlock_device(dev);
102    }
103
104    /* Detach this dcr only if the dev is initialized */
105    if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
106       dev->attached_dcrs->remove(dcr);  /* detach dcr from device */
107 //    remove_dcr_from_dcrs(dcr);      /* remove dcr from jcr list */
108    }
109    if (dcr->block) {
110       free_block(dcr->block);
111    }
112    if (dcr->rec) {
113       free_record(dcr->rec);
114    }
115    if (dcr->jcr) {
116       dcr->jcr->dcr = NULL;
117    }
118    free_unused_volume(dcr);           /* free unused vols attached to this dcr */
119    free(dcr);
120 }
121
122 /*********************************************************************
123  * Acquire device for reading. 
124  *  The drive should have previously been reserved by calling 
125  *  reserve_device_for_read(). We read the Volume label from the block and
126  *  leave the block pointers just after the label.
127  *
128  *  Returns: NULL if failed for any reason
129  *           dcr  if successful
130  */
131 DCR *acquire_device_for_read(DCR *dcr)
132 {
133    DEVICE *dev = dcr->dev;
134    JCR *jcr = dcr->jcr;
135    bool vol_ok = false;
136    bool tape_previously_mounted;
137    bool tape_initially_mounted;
138    VOL_LIST *vol;
139    bool try_autochanger = true;
140    int i;
141    int vol_label_status;
142    
143    dev->block(BST_DOING_ACQUIRE);
144
145    if (dev->num_writers > 0) {
146       Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"), 
147          dev->num_writers, jcr->JobId);
148       goto get_out;
149    }
150
151    /* Find next Volume, if any */
152    vol = jcr->VolList;
153    if (!vol) {
154       Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job %d canceled.\n"), jcr->JobId);
155       goto get_out;
156    }
157    jcr->CurVolume++;
158    for (i=1; i<jcr->CurVolume; i++) {
159       vol = vol->next;
160    }
161    if (!vol) {
162       goto get_out;                   /* should not happen */   
163    }
164    bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
165
166    init_device_wait_timers(dcr);
167
168    tape_previously_mounted = dev->can_read() || dev->can_append() ||
169                              dev->is_labeled();
170    tape_initially_mounted = tape_previously_mounted;
171
172
173    /* Volume info is always needed because of VolParts */
174    Dmsg0(200, "dir_get_volume_info\n");
175    if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
176       Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
177    }
178    
179    for (i=0; i<5; i++) {
180       dev->clear_labeled();              /* force reread of label */
181       if (job_canceled(jcr)) {
182          Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
183          goto get_out;                /* error return */
184       }
185       /*
186        * This code ensures that the device is ready for
187        * reading. If it is a file, it opens it.
188        * If it is a tape, it checks the volume name
189        */
190       Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
191       if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
192          if (dev->dev_errno == EIO) {   /* no tape loaded */
193            Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed (EIO): ERR=%s\n"),
194                  dev->print_name(), dcr->VolumeName, strerror_dev(dev));
195             goto default_path;
196          }
197          
198          Jmsg3(jcr, M_FATAL, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
199              dev->print_name(), dcr->VolumeName, strerror_dev(dev));
200          goto get_out;
201       }
202       Dmsg1(100, "opened dev %s OK\n", dev->print_name());
203       
204       /* Read Volume Label */
205       
206       Dmsg0(200, "calling read-vol-label\n");
207       vol_label_status = read_dev_volume_label(dcr);
208       switch (vol_label_status) {
209       case VOL_OK:
210          vol_ok = true;
211          memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
212          break;                    /* got it */
213       case VOL_IO_ERROR:
214          /*
215           * Send error message generated by read_dev_volume_label()
216           *  only we really had a tape mounted. This supresses superfluous
217           *  error messages when nothing is mounted.
218           */
219          if (tape_previously_mounted) {
220             Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
221          }
222          goto default_path;
223       case VOL_NAME_ERROR:
224          if (tape_initially_mounted) {
225             tape_initially_mounted = false;
226             goto default_path;
227          }
228          /* Fall through */
229       default:
230          Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
231 default_path:
232          tape_previously_mounted = true;
233          
234          /* If the device requires mount, close it, so the device can be ejected.
235           * FIXME: This should perhaps be done for all devices. */
236          if (dev->requires_mount()) {
237             force_close_device(dev);
238          }
239          
240          /* Call autochanger only once unless ask_sysop called */
241          if (try_autochanger) {
242             int stat;
243             Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
244                dcr->VolumeName, dcr->VolCatInfo.Slot);
245             stat = autoload_device(dcr, 0, NULL);
246             if (stat > 0) {
247                try_autochanger = false;
248                continue;              /* try reading volume mounted */
249             }
250          }
251          
252          /* Mount a specific volume and no other */
253          Dmsg0(200, "calling dir_ask_sysop\n");
254          if (!dir_ask_sysop_to_mount_volume(dcr)) {
255             goto get_out;             /* error return */
256          }
257          try_autochanger = true;      /* permit using autochanger again */
258          continue;                    /* try reading again */
259       } /* end switch */
260       break;
261    } /* end for loop */
262    if (!vol_ok) {
263       Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
264             dev->print_name());
265       goto get_out;
266    }
267
268    dev->clear_append();
269    dev->set_read();
270    set_jcr_job_status(jcr, JS_Running);
271    dir_send_job_status(jcr);
272    Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
273       dcr->VolumeName, dev->print_name());
274
275 get_out:
276    dev->unblock();
277    if (!vol_ok) {
278       free_dcr(dcr);
279       dcr = NULL;
280    }
281    return dcr;
282 }
283
284
285 /*
286  * Acquire device for writing. We permit multiple writers.
287  *  If this is the first one, we read the label.
288  *
289  *  Returns: NULL if failed for any reason
290  *           dcr if successful.
291  *   Note, normally reserve_device_for_append() is called
292  *   before this routine.
293  */
294 DCR *acquire_device_for_append(DCR *dcr)
295 {
296    bool release = false;
297    bool recycle = false;
298    bool do_mount = false;
299    DEVICE *dev = dcr->dev;
300    JCR *jcr = dcr->jcr;
301
302    init_device_wait_timers(dcr);
303
304    dev->block(BST_DOING_ACQUIRE);
305    Dmsg1(190, "acquire_append device is %s\n", dev->is_tape()?"tape":
306         (dev->is_dvd()?"DVD":"disk"));
307
308    if (dcr->reserved_device) {
309       dev->reserved_device--;
310       Dmsg1(200, "Dec reserve=%d\n", dev->reserved_device);
311       dcr->reserved_device = false;
312    }
313
314    /*
315     * With the reservation system, this should not happen
316     */
317    if (dev->can_read()) {
318       Jmsg1(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev->print_name());
319       Dmsg1(200, "Device %s is busy reading.\n", dev->print_name());
320       goto get_out;
321    }
322
323    if (dev->can_append()) {
324       Dmsg0(190, "device already in append.\n");
325       /*
326        * Device already in append mode
327        *
328        * Check if we have the right Volume mounted
329        *   OK if current volume info OK
330        *   OK if next volume matches current volume
331        *   otherwise mount desired volume obtained from
332        *    dir_find_next_appendable_volume
333        *  dev->VolHdr.VolumeName is what is in the drive
334        *  dcr->VolumeName is what we pass into the routines, or
335        *    get back from the subroutines.
336        */
337       bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
338       if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
339           !(dir_find_next_appendable_volume(dcr) &&
340             strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
341          Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName,
342             dcr->VolumeName);
343          /* Release volume reserved by dir_find_next_appendable_volume() */
344          if (dcr->VolumeName[0]) {
345             free_unused_volume(dcr);
346          }
347          if (dev->num_writers != 0) {
348             Jmsg3(jcr, M_FATAL, 0, _("Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n"), 
349                  dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
350             Dmsg3(200, "Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n",  
351                  dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
352             goto get_out;
353          }
354          /* Wrong tape mounted, release it, then fall through to get correct one */
355          Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
356          release = true;
357          do_mount = true;
358       } else {
359          /*
360           * At this point, the correct tape is already mounted, so
361           *   we do not need to do mount_next_write_volume(), unless
362           *   we need to recycle the tape.
363           */
364           recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
365           Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
366           if (recycle && dev->num_writers != 0) {
367              Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
368                   " on device %s because it is in use by another job.\n"),
369                   dev->VolHdr.VolumeName, dev->print_name());
370              goto get_out;
371           }
372           if (dev->num_writers == 0) {
373              memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
374           }
375       }
376    } else {
377       /* Not already in append mode, so mount the device */
378       Dmsg0(190, "Not in append mode, try mount.\n");
379       ASSERT(dev->num_writers == 0);
380       do_mount = true;
381    }
382
383    if (do_mount || recycle) {
384       Dmsg0(190, "Do mount_next_write_vol\n");
385       bool mounted = mount_next_write_volume(dcr, release);
386       if (!mounted) {
387          if (!job_canceled(jcr)) {
388             /* Reduce "noise" -- don't print if job canceled */
389             Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
390                dev->print_name());
391             Dmsg1(200, "Could not ready device %s for append.\n", 
392                dev->print_name());
393          }
394          goto get_out;
395       }
396    }
397
398    dev->num_writers++;                /* we are now a writer */
399    if (jcr->NumVolumes == 0) {
400       jcr->NumVolumes = 1;
401    }
402    goto ok_out;
403
404 /*
405  * If we jump here, it is an error return because
406  *  rtn_dev will still be NULL
407  */
408 get_out:
409    free_dcr(dcr);
410    dcr = NULL;
411 ok_out:
412    dev->unblock();
413    return dcr;
414 }
415
416 /*
417  * This job is done, so release the device. From a Unix standpoint,
418  *  the device remains open.
419  *
420  */
421 bool release_device(DCR *dcr)
422 {
423    JCR *jcr = dcr->jcr;
424    DEVICE *dev = dcr->dev;
425    bool ok = true;
426
427    lock_device(dev);
428    Dmsg1(100, "release_device device is %s\n", dev->is_tape()?"tape":"disk");
429
430    /* if device is reserved, job never started, so release the reserve here */
431    if (dcr->reserved_device) {
432       dev->reserved_device--;
433       Dmsg1(200, "Dec reserve=%d\n", dev->reserved_device);
434       dcr->reserved_device = false;
435    }
436
437    if (dev->can_read()) {
438       dev->clear_read();              /* clear read bit */
439
440       /******FIXME**** send read volume usage statistics to director */
441
442    } else if (dev->num_writers > 0) {
443       /* 
444        * Note if WEOT is set, we are at the end of the tape
445        *   and may not be positioned correctly, so the
446        *   job_media_record and update_vol_info have already been
447        *   done, which means we skip them here.
448        */
449       dev->num_writers--;
450       Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
451       if (dev->is_labeled()) {
452          Dmsg0(100, "dir_create_jobmedia_record. Release\n");
453          if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
454             Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
455                dcr->VolCatInfo.VolCatName, jcr->Job);
456          }
457          /* If no more writers, write an EOF */
458          if (!dev->num_writers && dev->can_write()) {
459             weof_dev(dev, 1);
460             write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
461          }
462          if (!dev->at_weot()) {
463             dev->VolCatInfo.VolCatFiles = dev->file;   /* set number of files */
464             dev->VolCatInfo.VolCatJobs++;              /* increment number of jobs */
465             /* Note! do volume update before close, which zaps VolCatInfo */
466             Dmsg0(100, "dir_update_vol_info. Release0\n");
467             dir_update_volume_info(dcr, false); /* send Volume info to Director */
468          }
469       }
470
471    } else {
472       /*                
473        * If we reach here, it is most likely because the job
474        *   has failed, since the device is not in read mode and
475        *   there are no writers. It was probably reserved.
476        */
477    }
478
479    /* If no writers, close if file or !CAP_ALWAYS_OPEN */
480    if (dev->num_writers == 0 && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
481       offline_or_rewind_dev(dev);
482       close_device(dev);
483    }
484
485    /* Fire off Alert command and include any output */
486    if (!job_canceled(jcr) && dcr->device->alert_command) {
487       POOLMEM *alert;
488       int status = 1;
489       BPIPE *bpipe;
490       char line[MAXSTRING];
491       alert = get_pool_memory(PM_FNAME);
492       alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
493       bpipe = open_bpipe(alert, 0, "r");
494       if (bpipe) {
495          while (fgets(line, sizeof(line), bpipe->rfd)) {
496             Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
497          }
498          status = close_bpipe(bpipe);
499       } else {
500          status = errno;
501       }
502       if (status != 0) {
503          berrno be;
504          Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
505               alert, be.strerror(status));
506       }
507
508       Dmsg1(400, "alert status=%d\n", status);
509       free_pool_memory(alert);
510    }
511    unlock_device(dev);
512    free_dcr(dcr);
513    jcr->dcr = NULL;
514    pthread_cond_broadcast(&wait_device_release);
515    return ok;
516 }