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