]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/acquire.c
Big backport from Enterprise
[bacula/bacula] / bacula / src / stored / acquire.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2017 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *  Routines to acquire and release a device for read/write
21  *
22  *   Written by Kern Sibbald, August MMII
23  */
24
25 #include "bacula.h"                   /* pull in global headers */
26 #include "stored.h"                   /* pull in Storage Deamon headers */
27
28 static int const rdbglvl = 100;
29
30 /* Forward referenced functions */
31 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol);
32
33 /*********************************************************************
34  * Acquire device for reading.
35  *  The drive should have previously been reserved by calling
36  *  reserve_device_for_read(). We read the Volume label from the block and
37  *  leave the block pointers just after the label.
38  *
39  *  Returns: false if failed for any reason
40  *           true  if successful
41  */
42 bool acquire_device_for_read(DCR *dcr)
43 {
44    DEVICE *dev;
45    JCR *jcr = dcr->jcr;
46    bool ok = false;
47    bool tape_previously_mounted;
48    VOL_LIST *vol;
49    bool try_autochanger = true;
50    int i;
51    int vol_label_status;
52    int retry = 0;
53
54    Enter(rdbglvl);
55    dev = dcr->dev;
56    ASSERT2(!dev->adata, "Called with adata dev. Wrong!");
57    dev->Lock_read_acquire();
58    Dmsg2(rdbglvl, "dcr=%p dev=%p\n", dcr, dcr->dev);
59    Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
60    dev->dblock(BST_DOING_ACQUIRE);
61
62    if (dev->num_writers > 0) {
63       Jmsg2(jcr, M_FATAL, 0, _("Acquire read: num_writers=%d not zero. Job %d canceled.\n"),
64          dev->num_writers, jcr->JobId);
65       goto get_out;
66    }
67
68    /* Find next Volume, if any */
69    vol = jcr->VolList;
70    if (!vol) {
71       char ed1[50];
72       Jmsg(jcr, M_FATAL, 0, _("No volumes specified for reading. Job %s canceled.\n"),
73          edit_int64(jcr->JobId, ed1));
74       goto get_out;
75    }
76    jcr->CurReadVolume++;
77    for (i=1; i<jcr->CurReadVolume; i++) {
78       vol = vol->next;
79    }
80    if (!vol) {
81       Jmsg(jcr, M_FATAL, 0, _("Logic error: no next volume to read. Numvol=%d Curvol=%d\n"),
82          jcr->NumReadVolumes, jcr->CurReadVolume);
83       goto get_out;                   /* should not happen */
84    }
85    set_dcr_from_vol(dcr, vol);
86
87    if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
88       Jmsg(jcr, M_FATAL, 0, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
89       goto get_out;
90    }
91
92    Dmsg2(rdbglvl, "Want Vol=%s Slot=%d\n", vol->VolumeName, vol->Slot);
93
94    /*
95     * If the MediaType requested for this volume is not the
96     *  same as the current drive, we attempt to find the same
97     *  device that was used to write the orginal volume.  If
98     *  found, we switch to using that device.
99     *
100     *  N.B. A lot of routines rely on the dcr pointer not changing
101     *    read_records.c even has multiple dcrs cached, so we take care
102     *    here to release all important parts of the dcr and re-acquire
103     *    them such as the block pointer (size may change), but we do
104     *    not release the dcr.
105     */
106    Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
107    if (dcr->media_type[0] && strcmp(dcr->media_type, dev->device->media_type) != 0) {
108       RCTX rctx;
109       DIRSTORE *store;
110       int stat;
111
112       Jmsg4(jcr, M_INFO, 0, _("Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
113                               "  %s device=%s\n"),
114             dcr->media_type, dev->device->media_type, dev->print_type(),
115             dev->print_name());
116       Dmsg4(rdbglvl, "Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
117                               "  %s device=%s\n",
118             dcr->media_type, dev->device->media_type,
119             dev->print_type(), dev->print_name());
120
121       generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
122
123       dev->dunblock(DEV_UNLOCKED);
124
125       lock_reservations();
126       memset(&rctx, 0, sizeof(RCTX));
127       rctx.jcr = jcr;
128       jcr->read_dcr = dcr;
129       jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
130       rctx.any_drive = true;
131       rctx.device_name = vol->device;
132       store = new DIRSTORE;
133       memset(store, 0, sizeof(DIRSTORE));
134       store->name[0] = 0; /* No storage name */
135       bstrncpy(store->media_type, vol->MediaType, sizeof(store->media_type));
136       bstrncpy(store->pool_name, dcr->pool_name, sizeof(store->pool_name));
137       bstrncpy(store->pool_type, dcr->pool_type, sizeof(store->pool_type));
138       store->append = false;
139       rctx.store = store;
140       clean_device(dcr);                     /* clean up the dcr */
141
142       /*
143        * Search for a new device
144        */
145       stat = search_res_for_device(rctx);
146       release_reserve_messages(jcr);         /* release queued messages */
147       unlock_reservations();
148
149       if (stat == 1) { /* found new device to use */
150          /*
151           * Switching devices, so acquire lock on new device,
152           *   then release the old one.
153           */
154          dcr->dev->Lock_read_acquire();      /* lock new one */
155          dev->Unlock_read_acquire();         /* release old one */
156          dev = dcr->dev;                     /* get new device pointer */
157          dev->dblock(BST_DOING_ACQUIRE);
158
159          dcr->VolumeName[0] = 0;
160          Jmsg(jcr, M_INFO, 0, _("Media Type change.  New read %s device %s chosen.\n"),
161             dev->print_type(), dev->print_name());
162          Dmsg2(50, "Media Type change.  New read %s device %s chosen.\n",
163             dev->print_type(), dev->print_name());
164          if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
165             Jmsg(jcr, M_FATAL, 0, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
166             goto get_out;
167          }
168          bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
169          dcr->setVolCatName(vol->VolumeName);
170          bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
171          dcr->VolCatInfo.Slot = vol->Slot;
172          dcr->VolCatInfo.InChanger = vol->Slot > 0;
173          bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name));
174          bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type));
175       } else {
176          /* error */
177          Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
178             vol->VolumeName);
179          Dmsg1(rdbglvl, "No suitable device found to read Volume \"%s\"\n", vol->VolumeName);
180          goto get_out;
181       }
182    }
183    Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
184
185    dev->clear_unload();
186
187    if (dev->vol && dev->vol->is_swapping()) {
188       dev->vol->set_slot(vol->Slot);
189       Dmsg3(rdbglvl, "swapping: slot=%d Vol=%s dev=%s\n", dev->vol->get_slot(),
190          dev->vol->vol_name, dev->print_name());
191    }
192
193    init_device_wait_timers(dcr);
194
195    tape_previously_mounted = dev->can_read() || dev->can_append() ||
196                              dev->is_labeled();
197 // tape_initially_mounted = tape_previously_mounted;
198
199    /* Volume info is always needed because of VolType */
200    Dmsg1(rdbglvl, "dir_get_volume_info vol=%s\n", dcr->VolumeName);
201    if (!dir_get_volume_info(dcr, dcr->VolumeName, GET_VOL_INFO_FOR_READ)) {
202       Dmsg2(rdbglvl, "dir_get_vol_info failed for vol=%s: %s\n",
203          dcr->VolumeName, jcr->errmsg);
204       Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
205    }
206    dev->set_load();                /* set to load volume */
207
208    for ( ;; ) {
209       /* If not polling limit retries */
210       if (!dev->poll && retry++ > 10) {
211          break;
212       }
213       dev->clear_labeled();              /* force reread of label */
214       if (job_canceled(jcr)) {
215          char ed1[50];
216          Mmsg1(dev->errmsg, _("Job %s canceled.\n"), edit_int64(jcr->JobId, ed1));
217          Jmsg(jcr, M_INFO, 0, dev->errmsg);
218          goto get_out;                /* error return */
219       }
220
221       dcr->do_unload();
222       dcr->do_swapping(SD_READ);
223       dcr->do_load(SD_READ);
224       set_dcr_from_vol(dcr, vol);          /* refresh dcr with desired volume info */
225
226       /*
227        * This code ensures that the device is ready for
228        * reading. If it is a file, it opens it.
229        * If it is a tape, it checks the volume name
230        */
231       Dmsg1(rdbglvl, "open vol=%s\n", dcr->VolumeName);
232       if (!dev->open_device(dcr, OPEN_READ_ONLY)) {
233          if (!dev->poll) {
234             Jmsg4(jcr, M_WARNING, 0, _("Read open %s device %s Volume \"%s\" failed: ERR=%s\n"),
235                   dev->print_type(), dev->print_name(), dcr->VolumeName, dev->bstrerror());
236          }
237          goto default_path;
238       }
239       Dmsg1(rdbglvl, "opened dev %s OK\n", dev->print_name());
240
241       /* Read Volume Label */
242       Dmsg0(rdbglvl, "calling read-vol-label\n");
243       vol_label_status = dev->read_dev_volume_label(dcr);
244       switch (vol_label_status) {
245       case VOL_OK:
246          Dmsg1(rdbglvl, "Got correct volume. VOL_OK: %s\n", dcr->VolCatInfo.VolCatName);
247          ok = true;
248          dev->VolCatInfo = dcr->VolCatInfo;     /* structure assignment */
249          break;                    /* got it */
250       case VOL_IO_ERROR:
251          Dmsg0(rdbglvl, "IO Error\n");
252          /*
253           * Send error message generated by dev->read_dev_volume_label()
254           *  only we really had a tape mounted. This supresses superfluous
255           *  error messages when nothing is mounted.
256           */
257          if (tape_previously_mounted) {
258             Jmsg(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
259          }
260          goto default_path;
261       case VOL_TYPE_ERROR:
262          Jmsg(jcr, M_FATAL, 0, "%s", jcr->errmsg);
263          goto get_out;
264       case VOL_NAME_ERROR:
265          Dmsg3(rdbglvl, "Vol name=%s want=%s drv=%s.\n", dev->VolHdr.VolumeName,
266                dcr->VolumeName, dev->print_name());
267          if (dev->is_volume_to_unload()) {
268             goto default_path;
269          }
270          dev->set_unload();              /* force unload of unwanted tape */
271          if (!unload_autochanger(dcr, -1)) {
272             /* at least free the device so we can re-open with correct volume */
273             dev->close(dcr);
274             free_volume(dev);
275          }
276          dev->set_load();
277          /* Fall through */
278       default:
279          Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
280 default_path:
281          Dmsg0(rdbglvl, "default path\n");
282          tape_previously_mounted = true;
283
284          /*
285           * If the device requires mount, close it, so the device can be ejected.
286           */
287          if (dev->requires_mount()) {
288             dev->close(dcr);
289             free_volume(dev);
290          }
291
292          /* Call autochanger only once unless ask_sysop called */
293          if (try_autochanger) {
294             int stat;
295             Dmsg2(rdbglvl, "calling autoload Vol=%s Slot=%d\n",
296                dcr->VolumeName, dcr->VolCatInfo.Slot);
297             stat = autoload_device(dcr, SD_READ, NULL);
298             if (stat > 0) {
299                try_autochanger = false;
300                continue;              /* try reading volume mounted */
301             }
302          }
303
304          /* Mount a specific volume and no other */
305          Dmsg0(rdbglvl, "calling dir_ask_sysop\n");
306          if (!dir_ask_sysop_to_mount_volume(dcr, SD_READ)) {
307             goto get_out;             /* error return */
308          }
309
310          /* Volume info is always needed because of VolType */
311          Dmsg1(150, "dir_get_volume_info vol=%s\n", dcr->VolumeName);
312          if (!dir_get_volume_info(dcr, dcr->VolumeName, GET_VOL_INFO_FOR_READ)) {
313             Dmsg2(150, "dir_get_vol_info failed for vol=%s: %s\n",
314                   dcr->VolumeName, jcr->errmsg);
315             Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
316          }
317          dev->set_load();                /* set to load volume */
318
319          try_autochanger = true;      /* permit trying the autochanger again */
320
321          continue;                    /* try reading again */
322       } /* end switch */
323       break;
324    } /* end for loop */
325
326    if (!ok) {
327       Jmsg2(jcr, M_FATAL, 0, _("Too many errors trying to mount %s device %s for reading.\n"),
328             dev->print_type(), dev->print_name());
329       goto get_out;
330    }
331
332    dev->clear_append();
333    dev->set_read();
334    jcr->sendJobStatus(JS_Running);
335    Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on %s device %s.\n"),
336       dcr->VolumeName, dev->print_type(), dev->print_name());
337
338 get_out:
339    dev->Lock();
340    /* If failed and not writing plugin close device */
341    if (!ok && dev->num_writers == 0 && dev->num_reserved() == 0) {
342       generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
343    }
344    /*
345     * Normally we are blocked, but in at least one error case above
346     *   we are not blocked because we unsuccessfully tried changing
347     *   devices.
348     */
349    if (dev->is_blocked()) {
350       dev->dunblock(DEV_LOCKED);
351    } else {
352       dev->Unlock();               /* dunblock() unlock the device too */
353    }
354    Dmsg2(rdbglvl, "dcr=%p dev=%p\n", dcr, dcr->dev);
355    Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
356    dev->Unlock_read_acquire();
357    Leave(rdbglvl);
358    return ok;
359 }
360
361 /*
362  * Acquire device for writing. We permit multiple writers.
363  *  If this is the first one, we read the label.
364  *
365  *  Returns: NULL if failed for any reason
366  *           dcr if successful.
367  *   Note, normally reserve_device_for_append() is called
368  *   before this routine.
369  */
370 DCR *acquire_device_for_append(DCR *dcr)
371 {
372    DEVICE *dev = dcr->dev;
373    JCR *jcr = dcr->jcr;
374    bool ok = false;
375    bool have_vol = false;
376
377    Enter(200);
378    dcr->set_ameta();
379    init_device_wait_timers(dcr);
380
381    dev->Lock_acquire();             /* only one job at a time */
382    dev->Lock();
383    Dmsg1(100, "acquire_append device is %s\n", dev->print_type());
384    /*
385     * With the reservation system, this should not happen
386     */
387    if (dev->can_read()) {
388       Mmsg2(jcr->errmsg, "Want to append but %s device %s is busy reading.\n",
389          dev->print_type(), dev->print_name());
390       Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
391       Dmsg0(50, jcr->errmsg);
392       goto get_out;
393    }
394
395    dev->clear_unload();
396
397    /*
398     * have_vol defines whether or not mount_next_write_volume should
399     *   ask the Director again about what Volume to use.
400     */
401    if (dev->can_append() && dcr->is_suitable_volume_mounted() &&
402        strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") != 0) {
403       Dmsg0(190, "device already in append.\n");
404       /*
405        * At this point, the correct tape is already mounted, so
406        *   we do not need to do mount_next_write_volume(), unless
407        *   we need to recycle the tape.
408        */
409        if (dev->num_writers == 0) {
410           dev->VolCatInfo = dcr->VolCatInfo;   /* structure assignment */
411        }
412        have_vol = dcr->is_tape_position_ok();
413    }
414
415    if (!have_vol) {
416       dev->rLock(true);
417       block_device(dev, BST_DOING_ACQUIRE);
418       dev->Unlock();
419       Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId);
420       if (!dcr->mount_next_write_volume()) {
421          if (!job_canceled(jcr)) {
422             /* Reduce "noise" -- don't print if job canceled */
423             Mmsg2(jcr->errmsg, _("Could not ready %s device %s for append.\n"),
424                dev->print_type(), dev->print_name());
425             Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
426             Dmsg0(50, jcr->errmsg);
427          }
428          dev->Lock();
429          unblock_device(dev);
430          goto get_out;
431       }
432       Dmsg2(190, "Output pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num);
433       dev->Lock();
434       unblock_device(dev);
435    }
436
437    if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
438       Mmsg0(jcr->errmsg,  _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
439       Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
440       Dmsg0(50, jcr->errmsg);
441       goto get_out;
442    }
443
444    dev->num_writers++;                /* we are now a writer */
445    if (jcr->NumWriteVolumes == 0) {
446       jcr->NumWriteVolumes = 1;
447    }
448    dev->VolCatInfo.VolCatJobs++;              /* increment number of jobs on vol */
449    Dmsg4(100, "=== nwriters=%d nres=%d vcatjob=%d dev=%s\n",
450       dev->num_writers, dev->num_reserved(), dev->VolCatInfo.VolCatJobs,
451       dev->print_name());
452    ok = dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
453
454 get_out:
455    /* Don't plugin close here, we might have multiple writers */
456    dcr->clear_reserved();
457    dev->Unlock();
458    dev->Unlock_acquire();
459    Leave(200);
460    return ok ? dcr : NULL;
461 }
462
463 /*
464  * This job is done, so release the device. From a Unix standpoint,
465  *  the device remains open.
466  *
467  * Note, if we were spooling, we may enter with the device blocked.
468  *   We unblock at the end, only if it was us who blocked the
469  *   device.
470  *
471  */
472 bool release_device(DCR *dcr)
473 {
474    JCR *jcr = dcr->jcr;
475    DEVICE *dev = dcr->dev;
476    bool ok = true;
477    char tbuf[100];
478    int was_blocked;
479
480
481    dev->Lock();
482    was_blocked = BST_NOT_BLOCKED;
483    if (!dev->is_blocked()) {
484       block_device(dev, BST_RELEASING);
485    } else {
486       was_blocked = dev->blocked();
487       dev->set_blocked(BST_RELEASING);
488    }
489    lock_volumes();
490    Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
491
492    /* if device is reserved, job never started, so release the reserve here */
493    dcr->clear_reserved();
494
495    if (dev->can_read()) {
496       VOLUME_CAT_INFO *vol = &dev->VolCatInfo;
497       generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
498       dev->clear_read();              /* clear read bit */
499       Dmsg2(150, "dir_update_vol_info. label=%d Vol=%s\n",
500          dev->is_labeled(), vol->VolCatName);
501       if (dev->is_labeled() && vol->VolCatName[0] != 0) {
502          dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
503          remove_read_volume(jcr, dcr->VolumeName);
504          volume_unused(dcr);
505       }
506    } else if (dev->num_writers > 0) {
507       /*
508        * Note if WEOT is set, we are at the end of the tape
509        *   and may not be positioned correctly, so the
510        *   job_media_record and update_vol_info have already been
511        *   done, which means we skip them here.
512        */
513       dev->num_writers--;
514       Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
515       if (dev->is_labeled()) {
516          if (!dev->at_weot()) {
517             Dmsg2(200, "dir_create_jobmedia. Release vol=%s dev=%s\n",
518                   dev->getVolCatName(), dev->print_name());
519          }
520          if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
521             Jmsg2(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
522                dcr->getVolCatName(), jcr->Job);
523          }
524          /* If no more writers, and no errors, and wrote something, write an EOF */
525          if (!dev->num_writers && dev->can_write() && dev->block_num > 0) {
526             dev->weof(dcr, 1);
527             write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
528          }
529          if (!dev->at_weot()) {
530             dev->VolCatInfo.VolCatFiles = dev->get_file();   /* set number of files */
531             /* Note! do volume update before close, which zaps VolCatInfo */
532             dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
533             Dmsg2(200, "dir_update_vol_info. Release vol=%s dev=%s\n",
534                   dev->getVolCatName(), dev->print_name());
535          }
536          if (dev->num_writers == 0) {         /* if not being used */
537             volume_unused(dcr);               /*  we obviously are not using the volume */
538             generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
539          }
540       }
541
542    } else {
543       /*
544        * If we reach here, it is most likely because the job
545        *   has failed, since the device is not in read mode and
546        *   there are no writers. It was probably reserved.
547        */
548       volume_unused(dcr);
549       generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
550    }
551    Dmsg3(100, "%d writers, %d reserve, dev=%s\n", dev->num_writers, dev->num_reserved(),
552          dev->print_name());
553
554    /* If no writers, close if file or !CAP_ALWAYS_OPEN */
555    if (dev->num_writers == 0 && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
556       generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
557       if (!dev->close(dcr) && dev->errmsg[0]) {
558          Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
559       }
560       free_volume(dev);
561    }
562    unlock_volumes();
563
564    /* Do new tape alert code */
565    dev->get_tape_alerts(dcr);
566    /* alert_callback is in tape_alert.c -- show only most recent (last) alert */
567    dev->show_tape_alerts(dcr, list_long, list_last, alert_callback);
568
569    pthread_cond_broadcast(&dev->wait_next_vol);
570    Dmsg2(100, "JobId=%u broadcast wait_device_release at %s\n",
571          (uint32_t)jcr->JobId, bstrftimes(tbuf, sizeof(tbuf), (utime_t)time(NULL)));
572    pthread_cond_broadcast(&wait_device_release);
573
574
575    /*
576     * If we are the thread that blocked the device, then unblock it
577     */
578    if (pthread_equal(dev->no_wait_id, pthread_self())) {
579       dev->dunblock(true);
580    } else {
581       /* Otherwise, reset the prior block status and unlock */
582       dev->set_blocked(was_blocked);
583       dev->Unlock();
584    }
585
586    dev->end_of_job(dcr);
587
588    if (dcr->keep_dcr) {
589       dev->detach_dcr_from_dev(dcr);
590    } else {
591       free_dcr(dcr);
592    }
593    Dmsg2(100, "Device %s released by JobId=%u\n", dev->print_name(),
594          (uint32_t)jcr->JobId);
595    return ok;
596 }
597
598 /*
599  * Clean up the device for reuse without freeing the memory
600  */
601 bool clean_device(DCR *dcr)
602 {
603    bool ok;
604    dcr->keep_dcr = true;                  /* do not free the dcr */
605    ok = release_device(dcr);
606    dcr->keep_dcr = false;
607    return ok;
608 }
609
610 /*
611  * Create a new Device Control Record and attach
612  *   it to the device (if this is a real job).
613  * Note, this has been updated so that it can be called first
614  *   without a DEVICE, then a second or third time with a DEVICE,
615  *   and each time, it should cleanup and point to the new device.
616  *   This should facilitate switching devices.
617  * Note, each dcr must point to the controlling job (jcr).  However,
618  *   a job can have multiple dcrs, so we must not store in the jcr's
619  *   structure as previously. The higher level routine must store
620  *   this dcr in the right place
621  *
622  */
623 DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev, bool writing)
624 {
625    DEVICE *odev;
626    if (!dcr) {
627       dcr = (DCR *)malloc(sizeof(DCR));
628       memset(dcr, 0, sizeof(DCR));
629       dcr->tid = pthread_self();
630       dcr->uploads = New(alist(100, false));
631       dcr->downloads = New(alist(100, false));
632       dcr->spool_fd = -1;
633    }
634    dcr->jcr = jcr;                 /* point back to jcr */
635    odev = dcr->dev;
636    if (dcr->attached_to_dev && odev) {
637       Dmsg2(100, "Detach 0x%x from olddev %s\n", dcr, odev->print_name());
638       odev->detach_dcr_from_dev(dcr);
639    }
640    ASSERT2(!dcr->attached_to_dev, "DCR is attached. Wrong!");
641    /* Set device information, possibly change device */
642    if (dev) {
643       ASSERT2(!dev->adata, "Called with adata dev. Wrong!");
644       dev->free_dcr_blocks(dcr);
645       dev->new_dcr_blocks(dcr);
646       if (dcr->rec) {
647          free_record(dcr->rec);
648       }
649       dcr->rec = new_record();
650       /* Use job spoolsize prior to device spoolsize */
651       if (jcr && jcr->spool_size) {
652          dcr->max_job_spool_size = jcr->spool_size;
653       } else {
654          dcr->max_job_spool_size = dev->device->max_job_spool_size;
655       }
656       dcr->device = dev->device;
657       dcr->set_dev(dev);
658       Dmsg2(100, "Attach 0x%x to dev %s\n", dcr, dev->print_name());
659       dev->attach_dcr_to_dev(dcr);
660    }
661    if (writing) {
662       dcr->set_writing();
663    } else {
664       dcr->clear_writing();
665    }
666    return dcr;
667 }
668
669 /*
670  * Search the dcrs list for the given dcr. If it is found,
671  *  as it should be, then remove it. Also zap the jcr pointer
672  *  to the dcr if it is the same one.
673  *
674  * Note, this code will be turned on when we can write to multiple
675  *  dcrs at the same time.
676  */
677 #ifdef needed
678 static void remove_dcr_from_dcrs(DCR *dcr)
679 {
680    JCR *jcr = dcr->jcr;
681    if (jcr->dcrs) {
682       int i = 0;
683       DCR *ldcr;
684       int num = jcr->dcrs->size();
685       for (i=0; i < num; i++) {
686          ldcr = (DCR *)jcr->dcrs->get(i);
687          if (ldcr == dcr) {
688             jcr->dcrs->remove(i);
689             if (jcr->dcr == dcr) {
690                jcr->dcr = NULL;
691             }
692          }
693       }
694    }
695 }
696 #endif
697
698 void DEVICE::attach_dcr_to_dev(DCR *dcr)
699 {
700    JCR *jcr = dcr->jcr;
701
702    Lock_dcrs();
703    jcr = dcr->jcr;
704    if (jcr) Dmsg1(500, "JobId=%u enter attach_dcr_to_dev\n", (uint32_t)jcr->JobId);
705    /* ***FIXME*** return error if dev not initiated */
706    if (!dcr->attached_to_dev && initiated && jcr && jcr->getJobType() != JT_SYSTEM) {
707       ASSERT2(!adata, "Called on adata dev. Wrong!");
708       Dmsg4(200, "Attach Jid=%d dcr=%p size=%d dev=%s\n", (uint32_t)jcr->JobId,
709          dcr, attached_dcrs->size(), print_name());
710       attached_dcrs->append(dcr);  /* attach dcr to device */
711       dcr->attached_to_dev = true;
712    }
713    Unlock_dcrs();
714 }
715
716 /*
717  * Note!! Do not enter with dev->Lock() since unreserve_device()
718  *   is going to lock it too.
719  */
720 void DEVICE::detach_dcr_from_dev(DCR *dcr)
721 {
722    Dmsg0(500, "Enter detach_dcr_from_dev\n"); /* jcr is NULL in some cases */
723
724    Lock();
725    Lock_dcrs();
726    /* Detach this dcr only if attached */
727    if (dcr->attached_to_dev) {
728       ASSERT2(!adata, "Called with adata dev. Wrong!");
729       dcr->unreserve_device(true);
730       Dmsg4(200, "Detach Jid=%d dcr=%p size=%d to dev=%s\n", (uint32_t)dcr->jcr->JobId,
731          dcr, attached_dcrs->size(), print_name());
732       dcr->attached_to_dev = false;
733       if (attached_dcrs->size()) {
734          attached_dcrs->remove(dcr);  /* detach dcr from device */
735       }
736    }
737    /* Check if someone accidentally left a drive reserved, and clear it */
738    if (attached_dcrs->size() == 0 && num_reserved() > 0) {
739       Pmsg3(000, "Warning!!! Detach %s DCR: dcrs=0 reserved=%d setting reserved==0. dev=%s\n",
740          dcr->is_writing() ? "writing" : "reading", num_reserved(), print_name());
741       m_num_reserved = 0;
742    }
743    dcr->attached_to_dev = false;
744    Unlock_dcrs();
745    Unlock();
746 }
747
748 /*
749  * Free up all aspects of the given dcr -- i.e. dechain it,
750  *  release allocated memory, zap pointers, ...
751  */
752 void free_dcr(DCR *dcr)
753 {
754    JCR *jcr;
755
756    jcr = dcr->jcr;
757
758    if (dcr->dev) {
759       dcr->dev->detach_dcr_from_dev(dcr);
760    }
761
762    if (dcr->dev) {
763       dcr->dev->free_dcr_blocks(dcr);
764    } else {
765       dcr->ameta_block = NULL;
766       free_block(dcr->block);
767    }
768    if (dcr->rec) {
769       free_record(dcr->rec);
770    }
771    if (jcr && jcr->dcr == dcr) {
772       jcr->dcr = NULL;
773    }
774    if (jcr && jcr->read_dcr == dcr) {
775       jcr->read_dcr = NULL;
776    }
777    delete dcr->uploads;
778    delete dcr->downloads;
779    free(dcr);
780 }
781
782 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol)
783 {
784    /*
785     * Note, if we want to be able to work from a .bsr file only
786     *  for disaster recovery, we must "simulate" reading the catalog
787     */
788    bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
789    dcr->setVolCatName(vol->VolumeName);
790    bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
791    dcr->VolCatInfo.Slot = vol->Slot;
792    dcr->VolCatInfo.InChanger = vol->Slot > 0;
793    dcr->CurrentVol = vol;   /* Keep VOL_LIST pointer (freed at the end of the job) */
794 }