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