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