2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2017 Kern Sibbald
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.
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.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Routines to acquire and release a device for read/write
22 * Written by Kern Sibbald, August MMII
25 #include "bacula.h" /* pull in global headers */
26 #include "stored.h" /* pull in Storage Deamon headers */
28 static int const rdbglvl = 100;
30 /* Forward referenced functions */
31 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol);
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.
39 * Returns: false if failed for any reason
42 bool acquire_device_for_read(DCR *dcr)
47 bool tape_previously_mounted;
49 bool try_autochanger = true;
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);
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);
68 /* Find next Volume, if any */
72 Jmsg(jcr, M_FATAL, 0, _("No volumes specified for reading. Job %s canceled.\n"),
73 edit_int64(jcr->JobId, ed1));
77 for (i=1; i<jcr->CurReadVolume; i++) {
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 */
85 set_dcr_from_vol(dcr, vol);
87 if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
88 Jmsg(jcr, M_FATAL, 0, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
92 Dmsg2(rdbglvl, "Want Vol=%s Slot=%d\n", vol->VolumeName, vol->Slot);
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.
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.
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) {
112 Jmsg4(jcr, M_INFO, 0, _("Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
114 dcr->media_type, dev->device->media_type, dev->print_type(),
116 Dmsg4(rdbglvl, "Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
118 dcr->media_type, dev->device->media_type,
119 dev->print_type(), dev->print_name());
121 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
123 dev->dunblock(DEV_UNLOCKED);
126 memset(&rctx, 0, sizeof(RCTX));
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;
140 clean_device(dcr); /* clean up the dcr */
143 * Search for a new device
145 stat = search_res_for_device(rctx);
146 release_reserve_messages(jcr); /* release queued messages */
147 unlock_reservations();
149 if (stat == 1) { /* found new device to use */
151 * Switching devices, so acquire lock on new device,
152 * then release the old one.
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);
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"));
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));
177 Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
179 Dmsg1(rdbglvl, "No suitable device found to read Volume \"%s\"\n", vol->VolumeName);
183 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
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());
193 init_device_wait_timers(dcr);
195 tape_previously_mounted = dev->can_read() || dev->can_append() ||
197 // tape_initially_mounted = tape_previously_mounted;
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);
206 dev->set_load(); /* set to load volume */
209 /* If not polling limit retries */
210 if (!dev->poll && retry++ > 10) {
213 dev->clear_labeled(); /* force reread of label */
214 if (job_canceled(jcr)) {
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 */
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 */
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
231 Dmsg1(rdbglvl, "open vol=%s\n", dcr->VolumeName);
232 if (!dev->open_device(dcr, OPEN_READ_ONLY)) {
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());
239 Dmsg1(rdbglvl, "opened dev %s OK\n", dev->print_name());
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) {
246 Dmsg1(rdbglvl, "Got correct volume. VOL_OK: %s\n", dcr->VolCatInfo.VolCatName);
248 dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
251 Dmsg0(rdbglvl, "IO Error\n");
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.
257 if (tape_previously_mounted) {
258 Jmsg(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
262 Jmsg(jcr, M_FATAL, 0, "%s", jcr->errmsg);
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()) {
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 */
279 Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
281 Dmsg0(rdbglvl, "default path\n");
282 tape_previously_mounted = true;
285 * If the device requires mount, close it, so the device can be ejected.
287 if (dev->requires_mount()) {
292 /* Call autochanger only once unless ask_sysop called */
293 if (try_autochanger) {
295 Dmsg2(rdbglvl, "calling autoload Vol=%s Slot=%d\n",
296 dcr->VolumeName, dcr->VolCatInfo.Slot);
297 stat = autoload_device(dcr, SD_READ, NULL);
299 try_autochanger = false;
300 continue; /* try reading volume mounted */
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 */
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);
317 dev->set_load(); /* set to load volume */
319 try_autochanger = true; /* permit trying the autochanger again */
321 continue; /* try reading again */
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());
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());
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);
345 * Normally we are blocked, but in at least one error case above
346 * we are not blocked because we unsuccessfully tried changing
349 if (dev->is_blocked()) {
350 dev->dunblock(DEV_LOCKED);
352 dev->Unlock(); /* dunblock() unlock the device too */
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();
362 * Acquire device for writing. We permit multiple writers.
363 * If this is the first one, we read the label.
365 * Returns: NULL if failed for any reason
367 * Note, normally reserve_device_for_append() is called
368 * before this routine.
370 DCR *acquire_device_for_append(DCR *dcr)
372 DEVICE *dev = dcr->dev;
375 bool have_vol = false;
379 init_device_wait_timers(dcr);
381 dev->Lock_acquire(); /* only one job at a time */
383 Dmsg1(100, "acquire_append device is %s\n", dev->print_type());
385 * With the reservation system, this should not happen
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);
398 * have_vol defines whether or not mount_next_write_volume should
399 * ask the Director again about what Volume to use.
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");
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.
409 if (dev->num_writers == 0) {
410 dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
412 have_vol = dcr->is_tape_position_ok();
417 block_device(dev, BST_DOING_ACQUIRE);
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);
432 Dmsg2(190, "Output pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num);
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);
444 dev->num_writers++; /* we are now a writer */
445 if (jcr->NumWriteVolumes == 0) {
446 jcr->NumWriteVolumes = 1;
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,
452 ok = dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
455 /* Don't plugin close here, we might have multiple writers */
456 dcr->clear_reserved();
458 dev->Unlock_acquire();
460 return ok ? dcr : NULL;
464 * This job is done, so release the device. From a Unix standpoint,
465 * the device remains open.
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
472 bool release_device(DCR *dcr)
475 DEVICE *dev = dcr->dev;
482 was_blocked = BST_NOT_BLOCKED;
483 if (!dev->is_blocked()) {
484 block_device(dev, BST_RELEASING);
486 was_blocked = dev->blocked();
487 dev->set_blocked(BST_RELEASING);
490 Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
492 /* if device is reserved, job never started, so release the reserve here */
493 dcr->clear_reserved();
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);
506 } else if (dev->num_writers > 0) {
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.
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());
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);
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) {
527 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
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());
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);
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.
549 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
551 Dmsg3(100, "%d writers, %d reserve, dev=%s\n", dev->num_writers, dev->num_reserved(),
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);
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);
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);
576 * If we are the thread that blocked the device, then unblock it
578 if (pthread_equal(dev->no_wait_id, pthread_self())) {
581 /* Otherwise, reset the prior block status and unlock */
582 dev->set_blocked(was_blocked);
586 dev->end_of_job(dcr);
589 dev->detach_dcr_from_dev(dcr);
593 Dmsg2(100, "Device %s released by JobId=%u\n", dev->print_name(),
594 (uint32_t)jcr->JobId);
599 * Clean up the device for reuse without freeing the memory
601 bool clean_device(DCR *dcr)
604 dcr->keep_dcr = true; /* do not free the dcr */
605 ok = release_device(dcr);
606 dcr->keep_dcr = false;
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
623 DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev, bool writing)
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));
634 dcr->jcr = jcr; /* point back to jcr */
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);
640 ASSERT2(!dcr->attached_to_dev, "DCR is attached. Wrong!");
641 /* Set device information, possibly change device */
643 ASSERT2(!dev->adata, "Called with adata dev. Wrong!");
644 dev->free_dcr_blocks(dcr);
645 dev->new_dcr_blocks(dcr);
647 free_record(dcr->rec);
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;
654 dcr->max_job_spool_size = dev->device->max_job_spool_size;
656 dcr->device = dev->device;
658 Dmsg2(100, "Attach 0x%x to dev %s\n", dcr, dev->print_name());
659 dev->attach_dcr_to_dev(dcr);
664 dcr->clear_writing();
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.
674 * Note, this code will be turned on when we can write to multiple
675 * dcrs at the same time.
678 static void remove_dcr_from_dcrs(DCR *dcr)
684 int num = jcr->dcrs->size();
685 for (i=0; i < num; i++) {
686 ldcr = (DCR *)jcr->dcrs->get(i);
688 jcr->dcrs->remove(i);
689 if (jcr->dcr == dcr) {
698 void DEVICE::attach_dcr_to_dev(DCR *dcr)
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;
717 * Note!! Do not enter with dev->Lock() since unreserve_device()
718 * is going to lock it too.
720 void DEVICE::detach_dcr_from_dev(DCR *dcr)
722 Dmsg0(500, "Enter detach_dcr_from_dev\n"); /* jcr is NULL in some cases */
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 */
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());
743 dcr->attached_to_dev = false;
749 * Free up all aspects of the given dcr -- i.e. dechain it,
750 * release allocated memory, zap pointers, ...
752 void free_dcr(DCR *dcr)
759 dcr->dev->detach_dcr_from_dev(dcr);
763 dcr->dev->free_dcr_blocks(dcr);
765 dcr->ameta_block = NULL;
766 free_block(dcr->block);
769 free_record(dcr->rec);
771 if (jcr && jcr->dcr == dcr) {
774 if (jcr && jcr->read_dcr == dcr) {
775 jcr->read_dcr = NULL;
778 delete dcr->downloads;
782 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol)
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
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) */