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