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