2 Bacula® - The Network Backup Solution
4 Copyright (C) 2002-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 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 Bacula® is a registered trademark of Kern Sibbald.
17 * Routines to acquire and release a device for read/write
19 * Written by Kern Sibbald, August MMII
23 #include "bacula.h" /* pull in global headers */
24 #include "stored.h" /* pull in Storage Deamon headers */
26 static int const rdbglvl = 100;
28 /* Forward referenced functions */
29 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol);
31 /*********************************************************************
32 * Acquire device for reading.
33 * The drive should have previously been reserved by calling
34 * reserve_device_for_read(). We read the Volume label from the block and
35 * leave the block pointers just after the label.
37 * Returns: NULL if failed for any reason
40 bool acquire_device_for_read(DCR *dcr)
45 bool tape_previously_mounted;
47 bool try_autochanger = true;
54 dev->Lock_read_acquire();
55 Dmsg2(rdbglvl, "dcr=%p dev=%p\n", dcr, dcr->dev);
56 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
57 dev->dblock(BST_DOING_ACQUIRE);
59 if (dev->num_writers > 0) {
60 Jmsg2(jcr, M_FATAL, 0, _("Acquire read: num_writers=%d not zero. Job %d canceled.\n"),
61 dev->num_writers, jcr->JobId);
65 /* Find next Volume, if any */
69 Jmsg(jcr, M_FATAL, 0, _("No volumes specified for reading. Job %s canceled.\n"),
70 edit_int64(jcr->JobId, ed1));
74 for (i=1; i<jcr->CurReadVolume; i++) {
78 Jmsg(jcr, M_FATAL, 0, _("Logic error: no next volume to read. Numvol=%d Curvol=%d\n"),
79 jcr->NumReadVolumes, jcr->CurReadVolume);
80 goto get_out; /* should not happen */
82 set_dcr_from_vol(dcr, vol);
84 if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
85 Jmsg(jcr, M_FATAL, 0, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
89 Dmsg2(rdbglvl, "Want Vol=%s Slot=%d\n", vol->VolumeName, vol->Slot);
92 * If the MediaType requested for this volume is not the
93 * same as the current drive, we attempt to find the same
94 * device that was used to write the orginal volume. If
95 * found, we switch to using that device.
97 * N.B. A lot of routines rely on the dcr pointer not changing
98 * read_records.c even has multiple dcrs cached, so we take care
99 * here to release all important parts of the dcr and re-acquire
100 * them such as the block pointer (size may change), but we do
101 * not release the dcr.
103 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
104 if (dcr->media_type[0] && strcmp(dcr->media_type, dev->device->media_type) != 0) {
109 Jmsg4(jcr, M_INFO, 0, _("Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
111 dcr->media_type, dev->device->media_type, dev->print_type(),
113 Dmsg4(rdbglvl, "Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
115 dcr->media_type, dev->device->media_type,
116 dev->print_type(), dev->print_name());
118 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
120 dev->dunblock(DEV_UNLOCKED);
123 memset(&rctx, 0, sizeof(RCTX));
126 jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
127 rctx.any_drive = true;
128 rctx.device_name = vol->device;
129 store = new DIRSTORE;
130 memset(store, 0, sizeof(DIRSTORE));
131 store->name[0] = 0; /* No storage name */
132 bstrncpy(store->media_type, vol->MediaType, sizeof(store->media_type));
133 bstrncpy(store->pool_name, dcr->pool_name, sizeof(store->pool_name));
134 bstrncpy(store->pool_type, dcr->pool_type, sizeof(store->pool_type));
135 store->append = false;
137 clean_device(dcr); /* clean up the dcr */
140 * Search for a new device
142 stat = search_res_for_device(rctx);
143 release_reserve_messages(jcr); /* release queued messages */
144 unlock_reservations();
146 if (stat == 1) { /* found new device to use */
148 * Switching devices, so acquire lock on new device,
149 * then release the old one.
151 dcr->dev->Lock_read_acquire(); /* lock new one */
152 dev->Unlock_read_acquire(); /* release old one */
153 dev = dcr->dev; /* get new device pointer */
154 dev->dblock(BST_DOING_ACQUIRE);
156 dcr->VolumeName[0] = 0;
157 Jmsg(jcr, M_INFO, 0, _("Media Type change. New read %s device %s chosen.\n"),
158 dev->print_type(), dev->print_name());
159 Dmsg2(50, "Media Type change. New read %s device %s chosen.\n",
160 dev->print_type(), dev->print_name());
161 if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
162 Jmsg(jcr, M_FATAL, 0, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
165 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
166 dcr->setVolCatName(vol->VolumeName);
167 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
168 dcr->VolCatInfo.Slot = vol->Slot;
169 dcr->VolCatInfo.InChanger = vol->Slot > 0;
170 bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name));
171 bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type));
174 Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
176 Dmsg1(rdbglvl, "No suitable device found to read Volume \"%s\"\n", vol->VolumeName);
180 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
184 if (dev->vol && dev->vol->is_swapping()) {
185 dev->vol->set_slot(vol->Slot);
186 Dmsg3(rdbglvl, "swapping: slot=%d Vol=%s dev=%s\n", dev->vol->get_slot(),
187 dev->vol->vol_name, dev->print_name());
190 init_device_wait_timers(dcr);
192 tape_previously_mounted = dev->can_read() || dev->can_append() ||
194 // tape_initially_mounted = tape_previously_mounted;
196 /* Volume info is always needed because of VolParts */
197 Dmsg1(rdbglvl, "dir_get_volume_info vol=%s\n", dcr->VolumeName);
198 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
199 Dmsg2(rdbglvl, "dir_get_vol_info failed for vol=%s: %s\n",
200 dcr->VolumeName, jcr->errmsg);
201 Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
203 dev->set_load(); /* set to load volume */
206 /* If not polling limit retries */
207 if (!dev->poll && retry++ > 10) {
210 dev->clear_labeled(); /* force reread of label */
211 if (job_canceled(jcr)) {
213 Mmsg1(dev->errmsg, _("Job %s canceled.\n"), edit_int64(jcr->JobId, ed1));
214 Jmsg(jcr, M_INFO, 0, dev->errmsg);
215 goto get_out; /* error return */
219 dcr->do_swapping(SD_READ);
220 dcr->do_load(SD_READ);
221 set_dcr_from_vol(dcr, vol); /* refresh dcr with desired volume info */
224 * This code ensures that the device is ready for
225 * reading. If it is a file, it opens it.
226 * If it is a tape, it checks the volume name
228 Dmsg1(rdbglvl, "open vol=%s\n", dcr->VolumeName);
229 if (!dev->open(dcr, OPEN_READ_ONLY)) {
231 Jmsg4(jcr, M_WARNING, 0, _("Read open %s device %s Volume \"%s\" failed: ERR=%s\n"),
232 dev->print_type(), dev->print_name(), dcr->VolumeName, dev->bstrerror());
236 Dmsg1(rdbglvl, "opened dev %s OK\n", dev->print_name());
238 /* Read Volume Label */
239 Dmsg0(rdbglvl, "calling read-vol-label\n");
240 vol_label_status = read_dev_volume_label(dcr);
241 switch (vol_label_status) {
243 Dmsg0(rdbglvl, "Got correct volume.\n");
245 dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
248 Dmsg0(rdbglvl, "IO Error\n");
250 * Send error message generated by read_dev_volume_label()
251 * only we really had a tape mounted. This supresses superfluous
252 * error messages when nothing is mounted.
254 if (tape_previously_mounted) {
255 Jmsg(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
259 Jmsg(jcr, M_FATAL, 0, dev->errmsg);
262 Dmsg3(rdbglvl, "Vol name=%s want=%s drv=%s.\n", dev->VolHdr.VolumeName,
263 dcr->VolumeName, dev->print_name());
264 if (dev->is_volume_to_unload()) {
267 dev->set_unload(); /* force unload of unwanted tape */
268 if (!unload_autochanger(dcr, -1)) {
269 /* at least free the device so we can re-open with correct volume */
276 Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
278 Dmsg0(rdbglvl, "default path\n");
279 tape_previously_mounted = true;
282 * If the device requires mount, close it, so the device can be ejected.
284 if (dev->requires_mount()) {
289 /* Call autochanger only once unless ask_sysop called */
290 if (try_autochanger) {
292 Dmsg2(rdbglvl, "calling autoload Vol=%s Slot=%d\n",
293 dcr->VolumeName, dcr->VolCatInfo.Slot);
294 stat = autoload_device(dcr, SD_READ, NULL);
296 try_autochanger = false;
297 continue; /* try reading volume mounted */
301 /* Mount a specific volume and no other */
302 Dmsg0(rdbglvl, "calling dir_ask_sysop\n");
303 if (!dir_ask_sysop_to_mount_volume(dcr, SD_READ)) {
304 goto get_out; /* error return */
307 /* Volume info is always needed because of VolParts */
308 Dmsg1(150, "dir_get_volume_info vol=%s\n", dcr->VolumeName);
309 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
310 Dmsg2(150, "dir_get_vol_info failed for vol=%s: %s\n",
311 dcr->VolumeName, jcr->errmsg);
312 Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
314 dev->set_load(); /* set to load volume */
316 try_autochanger = true; /* permit trying the autochanger again */
318 continue; /* try reading again */
324 Jmsg2(jcr, M_FATAL, 0, _("Too many errors trying to mount %s device %s for reading.\n"),
325 dev->print_type(), dev->print_name());
331 jcr->sendJobStatus(JS_Running);
332 Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on %s device %s.\n"),
333 dcr->VolumeName, dev->print_type(), dev->print_name());
337 dcr->clear_reserved();
338 /* If failed and not writing plugin close device */
339 if (!ok && dev->num_writers == 0 && dev->num_reserved() == 0) {
340 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
343 * Normally we are blocked, but in at least one error case above
344 * we are not blocked because we unsuccessfully tried changing
347 if (dev->is_blocked()) {
348 dev->dunblock(DEV_LOCKED);
350 dev->Unlock(); /* dunblock() unlock the device too */
352 Dmsg2(rdbglvl, "dcr=%p dev=%p\n", dcr, dcr->dev);
353 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
354 dev->Unlock_read_acquire();
360 * Acquire device for writing. We permit multiple writers.
361 * If this is the first one, we read the label.
363 * Returns: NULL if failed for any reason
365 * Note, normally reserve_device_for_append() is called
366 * before this routine.
368 DCR *acquire_device_for_append(DCR *dcr)
370 DEVICE *dev = dcr->dev;
373 bool have_vol = false;
376 init_device_wait_timers(dcr);
378 dev->Lock_acquire(); /* only one job at a time */
380 Dmsg1(100, "acquire_append device is %s\n", dev->is_tape()?"tape":
381 (dev->is_dvd()?"DVD":"disk"));
383 * With the reservation system, this should not happen
385 if (dev->can_read()) {
386 Mmsg2(jcr->errmsg, "Want to append but %s device %s is busy reading.\n",
387 dev->print_type(), dev->print_name());
388 Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
389 Dmsg0(50, jcr->errmsg);
396 * have_vol defines whether or not mount_next_write_volume should
397 * ask the Director again about what Volume to use.
399 if (dev->can_append() && dcr->is_suitable_volume_mounted() &&
400 strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") != 0) {
401 Dmsg0(190, "device already in append.\n");
403 * At this point, the correct tape is already mounted, so
404 * we do not need to do mount_next_write_volume(), unless
405 * we need to recycle the tape.
407 if (dev->num_writers == 0) {
408 dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
410 have_vol = dcr->is_tape_position_ok();
415 block_device(dev, BST_DOING_ACQUIRE);
417 Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId);
418 if (!dcr->mount_next_write_volume()) {
419 if (!job_canceled(jcr)) {
420 /* Reduce "noise" -- don't print if job canceled */
421 Mmsg2(jcr->errmsg, _("Could not ready %s device %s for append.\n"),
422 dev->print_type(), dev->print_name());
423 Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
424 Dmsg0(50, jcr->errmsg);
430 Dmsg2(190, "Output pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num);
435 if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
436 Mmsg0(jcr->errmsg, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
437 Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
438 Dmsg0(50, jcr->errmsg);
442 dev->num_writers++; /* we are now a writer */
443 if (jcr->NumWriteVolumes == 0) {
444 jcr->NumWriteVolumes = 1;
446 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */
447 Dmsg4(100, "=== nwriters=%d nres=%d vcatjob=%d dev=%s\n",
448 dev->num_writers, dev->num_reserved(), dev->VolCatInfo.VolCatJobs,
450 dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
454 /* Don't plugin close here, we might have multiple writers */
455 dcr->clear_reserved();
457 dev->Unlock_acquire();
459 return ok ? dcr : NULL;
463 * This job is done, so release the device. From a Unix standpoint,
464 * the device remains open.
466 * Note, if we were spooling, we may enter with the device blocked.
467 * We unblock at the end, only if it was us who blocked the
471 bool release_device(DCR *dcr)
474 DEVICE *dev = dcr->dev;
477 int was_blocked = BST_NOT_BLOCKED;
481 if (!dev->is_blocked()) {
482 block_device(dev, BST_RELEASING);
484 was_blocked = dev->blocked();
485 dev->set_blocked(BST_RELEASING);
488 Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
490 /* if device is reserved, job never started, so release the reserve here */
491 dcr->clear_reserved();
493 if (dev->can_read()) {
494 VOLUME_CAT_INFO *vol = &dev->VolCatInfo;
495 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
496 dev->clear_read(); /* clear read bit */
497 Dmsg2(150, "dir_update_vol_info. label=%d Vol=%s\n",
498 dev->is_labeled(), vol->VolCatName);
499 if (dev->is_labeled() && vol->VolCatName[0] != 0) {
500 dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
501 remove_read_volume(jcr, dcr->VolumeName);
504 } else if (dev->num_writers > 0) {
506 * Note if WEOT is set, we are at the end of the tape
507 * and may not be positioned correctly, so the
508 * job_media_record and update_vol_info have already been
509 * done, which means we skip them here.
512 Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
513 if (dev->is_labeled()) {
514 Dmsg2(200, "dir_create_jobmedia. Release vol=%s dev=%s\n",
515 dev->getVolCatName(), dev->print_name());
516 if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
517 Jmsg2(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
518 dcr->getVolCatName(), jcr->Job);
520 /* If no more writers, and no errors, and wrote something, write an EOF */
521 if (!dev->num_writers && dev->can_write() && dev->block_num > 0) {
523 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
525 if (!dev->at_weot()) {
526 dev->VolCatInfo.VolCatFiles = dev->get_file(); /* set number of files */
527 /* Note! do volume update before close, which zaps VolCatInfo */
528 dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
529 Dmsg2(200, "dir_update_vol_info. Release vol=%s dev=%s\n",
530 dev->getVolCatName(), dev->print_name());
532 if (dev->num_writers == 0) { /* if not being used */
533 volume_unused(dcr); /* we obviously are not using the volume */
534 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
540 * If we reach here, it is most likely because the job
541 * has failed, since the device is not in read mode and
542 * there are no writers. It was probably reserved.
545 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
547 Dmsg3(100, "%d writers, %d reserve, dev=%s\n", dev->num_writers, dev->num_reserved(),
550 /* If no writers, close if file or !CAP_ALWAYS_OPEN */
551 if (dev->num_writers == 0 && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
552 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
558 /* Fire off Alert command and include any output */
559 if (!job_canceled(jcr) && dcr->device->alert_command) {
563 char line[MAXSTRING];
564 alert = get_pool_memory(PM_FNAME);
565 alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
566 /* Wait maximum 5 minutes */
567 bpipe = open_bpipe(alert, 60 * 5, "r");
569 while (fgets(line, sizeof(line), bpipe->rfd)) {
570 Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
572 status = close_bpipe(bpipe);
578 Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
579 alert, be.bstrerror(status));
582 Dmsg1(400, "alert status=%d\n", status);
583 free_pool_memory(alert);
585 pthread_cond_broadcast(&dev->wait_next_vol);
586 Dmsg2(100, "JobId=%u broadcast wait_device_release at %s\n",
587 (uint32_t)jcr->JobId, bstrftimes(tbuf, sizeof(tbuf), (utime_t)time(NULL)));
588 pthread_cond_broadcast(&wait_device_release);
591 * If we are the thread that blocked the device, then unblock it
593 if (pthread_equal(dev->no_wait_id, pthread_self())) {
596 /* Otherwise, reset the prior block status and unlock */
597 dev->set_blocked(was_blocked);
602 dev->detach_dcr_from_dev(dcr);
606 Dmsg2(100, "Device %s released by JobId=%u\n", dev->print_name(),
607 (uint32_t)jcr->JobId);
612 * Clean up the device for reuse without freeing the memory
614 bool clean_device(DCR *dcr)
617 dcr->keep_dcr = true; /* do not free the dcr */
618 ok = release_device(dcr);
619 dcr->keep_dcr = false;
624 * Create a new Device Control Record and attach
625 * it to the device (if this is a real job).
626 * Note, this has been updated so that it can be called first
627 * without a DEVICE, then a second or third time with a DEVICE,
628 * and each time, it should cleanup and point to the new device.
629 * This should facilitate switching devices.
630 * Note, each dcr must point to the controlling job (jcr). However,
631 * a job can have multiple dcrs, so we must not store in the jcr's
632 * structure as previously. The higher level routine must store
633 * this dcr in the right place
636 DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev, bool writing)
640 dcr = (DCR *)malloc(sizeof(DCR));
641 memset(dcr, 0, sizeof(DCR));
642 dcr->tid = pthread_self();
645 dcr->jcr = jcr; /* point back to jcr */
647 if (dcr->attached_to_dev && odev) {
648 Dmsg2(100, "Detach 0x%x from olddev %s\n", dcr, odev->print_name());
649 odev->detach_dcr_from_dev(dcr);
651 ASSERT2(!dcr->attached_to_dev, "DCR is attached. Wrong!");
652 /* Set device information, possibly change device */
655 dcr->block = new_block(dev);
657 free_record(dcr->rec);
659 dcr->rec = new_record();
660 /* Use job spoolsize prior to device spoolsize */
661 if (jcr && jcr->spool_size) {
662 dcr->max_job_spool_size = jcr->spool_size;
664 dcr->max_job_spool_size = dev->device->max_job_spool_size;
666 dcr->device = dev->device;
668 Dmsg2(100, "Attach 0x%x to dev %s\n", dcr, dev->print_name());
669 dev->attach_dcr_to_dev(dcr);
674 dcr->clear_writing();
680 * Search the dcrs list for the given dcr. If it is found,
681 * as it should be, then remove it. Also zap the jcr pointer
682 * to the dcr if it is the same one.
684 * Note, this code will be turned on when we can write to multiple
685 * dcrs at the same time.
688 static void remove_dcr_from_dcrs(DCR *dcr)
694 int num = jcr->dcrs->size();
695 for (i=0; i < num; i++) {
696 ldcr = (DCR *)jcr->dcrs->get(i);
698 jcr->dcrs->remove(i);
699 if (jcr->dcr == dcr) {
708 void DEVICE::attach_dcr_to_dev(DCR *dcr)
714 if (jcr) Dmsg1(500, "JobId=%u enter attach_dcr_to_dev\n", (uint32_t)jcr->JobId);
715 /* ***FIXME*** return error if dev not initiated */
716 if (!dcr->attached_to_dev && initiated && jcr && jcr->getJobType() != JT_SYSTEM) {
717 Dmsg4(200, "Attach Jid=%d dcr=%p size=%d dev=%s\n", (uint32_t)jcr->JobId,
718 dcr, attached_dcrs->size(), print_name());
719 attached_dcrs->append(dcr); /* attach dcr to device */
720 dcr->attached_to_dev = true;
726 * Note!! Do not enter with dev->Lock() since unreserve_device()
727 * is going to lock it too.
729 void DEVICE::detach_dcr_from_dev(DCR *dcr)
731 Dmsg0(500, "Enter detach_dcr_from_dev\n"); /* jcr is NULL in some cases */
735 /* Detach this dcr only if attached */
736 if (dcr->attached_to_dev) {
737 dcr->unreserve_device(true);
738 Dmsg4(200, "Detach Jid=%d dcr=%p size=%d to dev=%s\n", (uint32_t)dcr->jcr->JobId,
739 dcr, attached_dcrs->size(), print_name());
740 dcr->attached_to_dev = false;
741 if (attached_dcrs->size()) {
742 attached_dcrs->remove(dcr); /* detach dcr from device */
745 dcr->attached_to_dev = false;
751 * Free up all aspects of the given dcr -- i.e. dechain it,
752 * release allocated memory, zap pointers, ...
754 void free_dcr(DCR *dcr)
761 dcr->dev->detach_dcr_from_dev(dcr);
766 free_record(dcr->rec);
768 if (jcr && jcr->dcr == dcr) {
771 if (jcr && jcr->read_dcr == dcr) {
772 jcr->read_dcr = NULL;
777 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol)
780 * Note, if we want to be able to work from a .bsr file only
781 * for disaster recovery, we must "simulate" reading the catalog
783 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
784 dcr->setVolCatName(vol->VolumeName);
785 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
786 dcr->VolCatInfo.Slot = vol->Slot;
787 dcr->VolCatInfo.InChanger = vol->Slot > 0;