2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2002-2014 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Routines to acquire and release a device for read/write
23 * Written by Kern Sibbald, August MMII
27 #include "bacula.h" /* pull in global headers */
28 #include "stored.h" /* pull in Storage Deamon headers */
30 static int const rdbglvl = 100;
32 /* Forward referenced functions */
33 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol);
35 /*********************************************************************
36 * Acquire device for reading.
37 * The drive should have previously been reserved by calling
38 * reserve_device_for_read(). We read the Volume label from the block and
39 * leave the block pointers just after the label.
41 * Returns: false if failed for any reason
44 bool acquire_device_for_read(DCR *dcr)
49 bool tape_previously_mounted;
51 bool try_autochanger = true;
58 dev->Lock_read_acquire();
59 Dmsg2(rdbglvl, "dcr=%p dev=%p\n", dcr, dcr->dev);
60 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
61 dev->dblock(BST_DOING_ACQUIRE);
63 if (dev->num_writers > 0) {
64 Jmsg2(jcr, M_FATAL, 0, _("Acquire read: num_writers=%d not zero. Job %d canceled.\n"),
65 dev->num_writers, jcr->JobId);
69 /* Find next Volume, if any */
73 Jmsg(jcr, M_FATAL, 0, _("No volumes specified for reading. Job %s canceled.\n"),
74 edit_int64(jcr->JobId, ed1));
78 for (i=1; i<jcr->CurReadVolume; i++) {
82 Jmsg(jcr, M_FATAL, 0, _("Logic error: no next volume to read. Numvol=%d Curvol=%d\n"),
83 jcr->NumReadVolumes, jcr->CurReadVolume);
84 goto get_out; /* should not happen */
86 set_dcr_from_vol(dcr, vol);
88 if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
89 Jmsg(jcr, M_FATAL, 0, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
93 Dmsg2(rdbglvl, "Want Vol=%s Slot=%d\n", vol->VolumeName, vol->Slot);
96 * If the MediaType requested for this volume is not the
97 * same as the current drive, we attempt to find the same
98 * device that was used to write the orginal volume. If
99 * found, we switch to using that device.
101 * N.B. A lot of routines rely on the dcr pointer not changing
102 * read_records.c even has multiple dcrs cached, so we take care
103 * here to release all important parts of the dcr and re-acquire
104 * them such as the block pointer (size may change), but we do
105 * not release the dcr.
107 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
108 if (dcr->media_type[0] && strcmp(dcr->media_type, dev->device->media_type) != 0) {
113 Jmsg4(jcr, M_INFO, 0, _("Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
115 dcr->media_type, dev->device->media_type, dev->print_type(),
117 Dmsg4(rdbglvl, "Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
119 dcr->media_type, dev->device->media_type,
120 dev->print_type(), dev->print_name());
122 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
124 dev->dunblock(DEV_UNLOCKED);
127 memset(&rctx, 0, sizeof(RCTX));
130 jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
131 rctx.any_drive = true;
132 rctx.device_name = vol->device;
133 store = new DIRSTORE;
134 memset(store, 0, sizeof(DIRSTORE));
135 store->name[0] = 0; /* No storage name */
136 bstrncpy(store->media_type, vol->MediaType, sizeof(store->media_type));
137 bstrncpy(store->pool_name, dcr->pool_name, sizeof(store->pool_name));
138 bstrncpy(store->pool_type, dcr->pool_type, sizeof(store->pool_type));
139 store->append = false;
141 clean_device(dcr); /* clean up the dcr */
144 * Search for a new device
146 stat = search_res_for_device(rctx);
147 release_reserve_messages(jcr); /* release queued messages */
148 unlock_reservations();
150 if (stat == 1) { /* found new device to use */
152 * Switching devices, so acquire lock on new device,
153 * then release the old one.
155 dcr->dev->Lock_read_acquire(); /* lock new one */
156 dev->Unlock_read_acquire(); /* release old one */
157 dev = dcr->dev; /* get new device pointer */
158 dev->dblock(BST_DOING_ACQUIRE);
160 dcr->VolumeName[0] = 0;
161 Jmsg(jcr, M_INFO, 0, _("Media Type change. New read %s device %s chosen.\n"),
162 dev->print_type(), dev->print_name());
163 Dmsg2(50, "Media Type change. New read %s device %s chosen.\n",
164 dev->print_type(), dev->print_name());
165 if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
166 Jmsg(jcr, M_FATAL, 0, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
169 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
170 dcr->setVolCatName(vol->VolumeName);
171 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
172 dcr->VolCatInfo.Slot = vol->Slot;
173 dcr->VolCatInfo.InChanger = vol->Slot > 0;
174 bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name));
175 bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type));
178 Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
180 Dmsg1(rdbglvl, "No suitable device found to read Volume \"%s\"\n", vol->VolumeName);
184 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
188 if (dev->vol && dev->vol->is_swapping()) {
189 dev->vol->set_slot(vol->Slot);
190 Dmsg3(rdbglvl, "swapping: slot=%d Vol=%s dev=%s\n", dev->vol->get_slot(),
191 dev->vol->vol_name, dev->print_name());
194 init_device_wait_timers(dcr);
196 tape_previously_mounted = dev->can_read() || dev->can_append() ||
198 // tape_initially_mounted = tape_previously_mounted;
200 /* Volume info is always needed because of VolType */
201 Dmsg1(rdbglvl, "dir_get_volume_info vol=%s\n", dcr->VolumeName);
202 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
203 Dmsg2(rdbglvl, "dir_get_vol_info failed for vol=%s: %s\n",
204 dcr->VolumeName, jcr->errmsg);
205 Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
207 dev->set_load(); /* set to load volume */
210 /* If not polling limit retries */
211 if (!dev->poll && retry++ > 10) {
214 dev->clear_labeled(); /* force reread of label */
215 if (job_canceled(jcr)) {
217 Mmsg1(dev->errmsg, _("Job %s canceled.\n"), edit_int64(jcr->JobId, ed1));
218 Jmsg(jcr, M_INFO, 0, dev->errmsg);
219 goto get_out; /* error return */
223 dcr->do_swapping(SD_READ);
224 dcr->do_load(SD_READ);
225 set_dcr_from_vol(dcr, vol); /* refresh dcr with desired volume info */
228 * This code ensures that the device is ready for
229 * reading. If it is a file, it opens it.
230 * If it is a tape, it checks the volume name
232 Dmsg1(rdbglvl, "open vol=%s\n", dcr->VolumeName);
233 if (!dev->open(dcr, OPEN_READ_ONLY)) {
235 Jmsg4(jcr, M_WARNING, 0, _("Read open %s device %s Volume \"%s\" failed: ERR=%s\n"),
236 dev->print_type(), dev->print_name(), dcr->VolumeName, dev->bstrerror());
240 Dmsg1(rdbglvl, "opened dev %s OK\n", dev->print_name());
242 /* Read Volume Label */
243 Dmsg0(rdbglvl, "calling read-vol-label\n");
244 vol_label_status = read_dev_volume_label(dcr);
245 switch (vol_label_status) {
247 Dmsg0(rdbglvl, "Got correct volume.\n");
249 dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
252 Dmsg0(rdbglvl, "IO Error\n");
254 * Send error message generated by read_dev_volume_label()
255 * only we really had a tape mounted. This supresses superfluous
256 * error messages when nothing is mounted.
258 if (tape_previously_mounted) {
259 Jmsg(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
263 Jmsg(jcr, M_FATAL, 0, dev->errmsg);
266 Dmsg3(rdbglvl, "Vol name=%s want=%s drv=%s.\n", dev->VolHdr.VolumeName,
267 dcr->VolumeName, dev->print_name());
268 if (dev->is_volume_to_unload()) {
271 dev->set_unload(); /* force unload of unwanted tape */
272 if (!unload_autochanger(dcr, -1)) {
273 /* at least free the device so we can re-open with correct volume */
280 Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
282 Dmsg0(rdbglvl, "default path\n");
283 tape_previously_mounted = true;
286 * If the device requires mount, close it, so the device can be ejected.
288 if (dev->requires_mount()) {
293 /* Call autochanger only once unless ask_sysop called */
294 if (try_autochanger) {
296 Dmsg2(rdbglvl, "calling autoload Vol=%s Slot=%d\n",
297 dcr->VolumeName, dcr->VolCatInfo.Slot);
298 stat = autoload_device(dcr, SD_READ, NULL);
300 try_autochanger = false;
301 continue; /* try reading volume mounted */
305 /* Mount a specific volume and no other */
306 Dmsg0(rdbglvl, "calling dir_ask_sysop\n");
307 if (!dir_ask_sysop_to_mount_volume(dcr, SD_READ)) {
308 goto get_out; /* error return */
311 /* Volume info is always needed because of VolType */
312 Dmsg1(150, "dir_get_volume_info vol=%s\n", dcr->VolumeName);
313 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
314 Dmsg2(150, "dir_get_vol_info failed for vol=%s: %s\n",
315 dcr->VolumeName, jcr->errmsg);
316 Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
318 dev->set_load(); /* set to load volume */
320 try_autochanger = true; /* permit trying the autochanger again */
322 continue; /* try reading again */
328 Jmsg2(jcr, M_FATAL, 0, _("Too many errors trying to mount %s device %s for reading.\n"),
329 dev->print_type(), dev->print_name());
335 jcr->sendJobStatus(JS_Running);
336 Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on %s device %s.\n"),
337 dcr->VolumeName, dev->print_type(), dev->print_name());
341 dcr->clear_reserved();
342 /* If failed and not writing plugin close device */
343 if (!ok && dev->num_writers == 0 && dev->num_reserved() == 0) {
344 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
347 * Normally we are blocked, but in at least one error case above
348 * we are not blocked because we unsuccessfully tried changing
351 if (dev->is_blocked()) {
352 dev->dunblock(DEV_LOCKED);
354 dev->Unlock(); /* dunblock() unlock the device too */
356 Dmsg2(rdbglvl, "dcr=%p dev=%p\n", dcr, dcr->dev);
357 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
358 dev->Unlock_read_acquire();
364 * Acquire device for writing. We permit multiple writers.
365 * If this is the first one, we read the label.
367 * Returns: NULL if failed for any reason
369 * Note, normally reserve_device_for_append() is called
370 * before this routine.
372 DCR *acquire_device_for_append(DCR *dcr)
374 DEVICE *dev = dcr->dev;
377 bool have_vol = false;
380 init_device_wait_timers(dcr);
382 dev->Lock_acquire(); /* only one job at a time */
384 Dmsg1(100, "acquire_append device is %s\n", dev->is_tape()?"tape":
385 (dev->is_dvd()?"DVD":"disk"));
387 * With the reservation system, this should not happen
389 if (dev->can_read()) {
390 Mmsg2(jcr->errmsg, "Want to append but %s device %s is busy reading.\n",
391 dev->print_type(), dev->print_name());
392 Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
393 Dmsg0(50, jcr->errmsg);
400 * have_vol defines whether or not mount_next_write_volume should
401 * ask the Director again about what Volume to use.
403 if (dev->can_append() && dcr->is_suitable_volume_mounted() &&
404 strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") != 0) {
405 Dmsg0(190, "device already in append.\n");
407 * At this point, the correct tape is already mounted, so
408 * we do not need to do mount_next_write_volume(), unless
409 * we need to recycle the tape.
411 if (dev->num_writers == 0) {
412 dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
414 have_vol = dcr->is_tape_position_ok();
419 block_device(dev, BST_DOING_ACQUIRE);
421 Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId);
422 if (!dcr->mount_next_write_volume()) {
423 if (!job_canceled(jcr)) {
424 /* Reduce "noise" -- don't print if job canceled */
425 Mmsg2(jcr->errmsg, _("Could not ready %s device %s for append.\n"),
426 dev->print_type(), dev->print_name());
427 Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
428 Dmsg0(50, jcr->errmsg);
434 Dmsg2(190, "Output pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num);
439 if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
440 Mmsg0(jcr->errmsg, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
441 Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
442 Dmsg0(50, jcr->errmsg);
446 dev->num_writers++; /* we are now a writer */
447 if (jcr->NumWriteVolumes == 0) {
448 jcr->NumWriteVolumes = 1;
450 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */
451 Dmsg4(100, "=== nwriters=%d nres=%d vcatjob=%d dev=%s\n",
452 dev->num_writers, dev->num_reserved(), dev->VolCatInfo.VolCatJobs,
454 ok = dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
457 /* Don't plugin close here, we might have multiple writers */
458 dcr->clear_reserved();
460 dev->Unlock_acquire();
462 return ok ? dcr : NULL;
466 * This job is done, so release the device. From a Unix standpoint,
467 * the device remains open.
469 * Note, if we were spooling, we may enter with the device blocked.
470 * We unblock at the end, only if it was us who blocked the
474 bool release_device(DCR *dcr)
477 DEVICE *dev = dcr->dev;
480 int was_blocked = BST_NOT_BLOCKED;
484 if (!dev->is_blocked()) {
485 block_device(dev, BST_RELEASING);
487 was_blocked = dev->blocked();
488 dev->set_blocked(BST_RELEASING);
491 Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
493 /* if device is reserved, job never started, so release the reserve here */
494 dcr->clear_reserved();
496 if (dev->can_read()) {
497 VOLUME_CAT_INFO *vol = &dev->VolCatInfo;
498 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
499 dev->clear_read(); /* clear read bit */
500 Dmsg2(150, "dir_update_vol_info. label=%d Vol=%s\n",
501 dev->is_labeled(), vol->VolCatName);
502 if (dev->is_labeled() && vol->VolCatName[0] != 0) {
503 dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
504 remove_read_volume(jcr, dcr->VolumeName);
507 } else if (dev->num_writers > 0) {
509 * Note if WEOT is set, we are at the end of the tape
510 * and may not be positioned correctly, so the
511 * job_media_record and update_vol_info have already been
512 * done, which means we skip them here.
515 Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
516 if (dev->is_labeled()) {
517 Dmsg2(200, "dir_create_jobmedia. Release vol=%s dev=%s\n",
518 dev->getVolCatName(), dev->print_name());
519 if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
520 Jmsg2(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
521 dcr->getVolCatName(), jcr->Job);
523 /* If no more writers, and no errors, and wrote something, write an EOF */
524 if (!dev->num_writers && dev->can_write() && dev->block_num > 0) {
526 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
528 if (!dev->at_weot()) {
529 dev->VolCatInfo.VolCatFiles = dev->get_file(); /* set number of files */
530 /* Note! do volume update before close, which zaps VolCatInfo */
531 dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
532 Dmsg2(200, "dir_update_vol_info. Release vol=%s dev=%s\n",
533 dev->getVolCatName(), dev->print_name());
535 if (dev->num_writers == 0) { /* if not being used */
536 volume_unused(dcr); /* we obviously are not using the volume */
537 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
543 * If we reach here, it is most likely because the job
544 * has failed, since the device is not in read mode and
545 * there are no writers. It was probably reserved.
548 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
550 Dmsg3(100, "%d writers, %d reserve, dev=%s\n", dev->num_writers, dev->num_reserved(),
553 /* If no writers, close if file or !CAP_ALWAYS_OPEN */
554 if (dev->num_writers == 0 && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
555 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
557 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
563 /* Fire off Alert command and include any output */
564 if (!job_canceled(jcr) && dcr->device->alert_command) {
568 char line[MAXSTRING];
569 alert = get_pool_memory(PM_FNAME);
570 alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
571 /* Wait maximum 5 minutes */
572 bpipe = open_bpipe(alert, 60 * 5, "r");
574 while (fgets(line, sizeof(line), bpipe->rfd)) {
575 Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
577 status = close_bpipe(bpipe);
583 Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
584 alert, be.bstrerror(status));
587 Dmsg1(400, "alert status=%d\n", status);
588 free_pool_memory(alert);
590 pthread_cond_broadcast(&dev->wait_next_vol);
591 Dmsg2(100, "JobId=%u broadcast wait_device_release at %s\n",
592 (uint32_t)jcr->JobId, bstrftimes(tbuf, sizeof(tbuf), (utime_t)time(NULL)));
593 pthread_cond_broadcast(&wait_device_release);
596 * If we are the thread that blocked the device, then unblock it
598 if (pthread_equal(dev->no_wait_id, pthread_self())) {
601 /* Otherwise, reset the prior block status and unlock */
602 dev->set_blocked(was_blocked);
607 dev->detach_dcr_from_dev(dcr);
611 Dmsg2(100, "Device %s released by JobId=%u\n", dev->print_name(),
612 (uint32_t)jcr->JobId);
617 * Clean up the device for reuse without freeing the memory
619 bool clean_device(DCR *dcr)
622 dcr->keep_dcr = true; /* do not free the dcr */
623 ok = release_device(dcr);
624 dcr->keep_dcr = false;
629 * Create a new Device Control Record and attach
630 * it to the device (if this is a real job).
631 * Note, this has been updated so that it can be called first
632 * without a DEVICE, then a second or third time with a DEVICE,
633 * and each time, it should cleanup and point to the new device.
634 * This should facilitate switching devices.
635 * Note, each dcr must point to the controlling job (jcr). However,
636 * a job can have multiple dcrs, so we must not store in the jcr's
637 * structure as previously. The higher level routine must store
638 * this dcr in the right place
641 DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev, bool writing)
645 dcr = (DCR *)malloc(sizeof(DCR));
646 memset(dcr, 0, sizeof(DCR));
647 dcr->tid = pthread_self();
650 dcr->jcr = jcr; /* point back to jcr */
652 if (dcr->attached_to_dev && odev) {
653 Dmsg2(100, "Detach 0x%x from olddev %s\n", dcr, odev->print_name());
654 odev->detach_dcr_from_dev(dcr);
656 ASSERT2(!dcr->attached_to_dev, "DCR is attached. Wrong!");
657 /* Set device information, possibly change device */
660 dcr->block = new_block(dev);
661 dcr->ameta_block = dcr->block;
663 free_record(dcr->rec);
665 dcr->rec = new_record();
666 /* Use job spoolsize prior to device spoolsize */
667 if (jcr && jcr->spool_size) {
668 dcr->max_job_spool_size = jcr->spool_size;
670 dcr->max_job_spool_size = dev->device->max_job_spool_size;
672 dcr->device = dev->device;
674 Dmsg2(100, "Attach 0x%x to dev %s\n", dcr, dev->print_name());
675 dev->attach_dcr_to_dev(dcr);
680 dcr->clear_writing();
686 * Search the dcrs list for the given dcr. If it is found,
687 * as it should be, then remove it. Also zap the jcr pointer
688 * to the dcr if it is the same one.
690 * Note, this code will be turned on when we can write to multiple
691 * dcrs at the same time.
694 static void remove_dcr_from_dcrs(DCR *dcr)
700 int num = jcr->dcrs->size();
701 for (i=0; i < num; i++) {
702 ldcr = (DCR *)jcr->dcrs->get(i);
704 jcr->dcrs->remove(i);
705 if (jcr->dcr == dcr) {
714 void DEVICE::attach_dcr_to_dev(DCR *dcr)
720 if (jcr) Dmsg1(500, "JobId=%u enter attach_dcr_to_dev\n", (uint32_t)jcr->JobId);
721 /* ***FIXME*** return error if dev not initiated */
722 if (!dcr->attached_to_dev && initiated && jcr && jcr->getJobType() != JT_SYSTEM) {
723 Dmsg4(200, "Attach Jid=%d dcr=%p size=%d dev=%s\n", (uint32_t)jcr->JobId,
724 dcr, attached_dcrs->size(), print_name());
725 attached_dcrs->append(dcr); /* attach dcr to device */
726 dcr->attached_to_dev = true;
732 * Note!! Do not enter with dev->Lock() since unreserve_device()
733 * is going to lock it too.
735 void DEVICE::detach_dcr_from_dev(DCR *dcr)
737 Dmsg0(500, "Enter detach_dcr_from_dev\n"); /* jcr is NULL in some cases */
741 /* Detach this dcr only if attached */
742 if (dcr->attached_to_dev) {
743 dcr->unreserve_device(true);
744 Dmsg4(200, "Detach Jid=%d dcr=%p size=%d to dev=%s\n", (uint32_t)dcr->jcr->JobId,
745 dcr, attached_dcrs->size(), print_name());
746 dcr->attached_to_dev = false;
747 if (attached_dcrs->size()) {
748 attached_dcrs->remove(dcr); /* detach dcr from device */
751 /* Check if someone accidentally left a drive reserved, and clear it */
752 if (attached_dcrs->size() == 0 && num_reserved() > 0) {
753 Pmsg2(000, "Warning!!! dcrs=0 reserved=%d setting reserved==0. dev=%s\n",
754 num_reserved(), print_name());
757 dcr->attached_to_dev = false;
763 * Free up all aspects of the given dcr -- i.e. dechain it,
764 * release allocated memory, zap pointers, ...
766 void free_dcr(DCR *dcr)
773 dcr->dev->detach_dcr_from_dev(dcr);
778 free_record(dcr->rec);
780 if (jcr && jcr->dcr == dcr) {
783 if (jcr && jcr->read_dcr == dcr) {
784 jcr->read_dcr = NULL;
789 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol)
792 * Note, if we want to be able to work from a .bsr file only
793 * for disaster recovery, we must "simulate" reading the catalog
795 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
796 dcr->setVolCatName(vol->VolumeName);
797 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
798 dcr->VolCatInfo.Slot = vol->Slot;
799 dcr->VolCatInfo.InChanger = vol->Slot > 0;