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