2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 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
26 #include "bacula.h" /* pull in global headers */
27 #include "stored.h" /* pull in Storage Deamon headers */
29 static int const rdbglvl = 100;
31 /* Forward referenced functions */
32 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol);
34 /*********************************************************************
35 * Acquire device for reading.
36 * The drive should have previously been reserved by calling
37 * reserve_device_for_read(). We read the Volume label from the block and
38 * leave the block pointers just after the label.
40 * Returns: false if failed for any reason
43 bool acquire_device_for_read(DCR *dcr)
48 bool tape_previously_mounted;
50 bool try_autochanger = true;
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, 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(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 = read_dev_volume_label(dcr);
244 switch (vol_label_status) {
246 Dmsg0(rdbglvl, "Got correct volume.\n");
248 dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
251 Dmsg0(rdbglvl, "IO Error\n");
253 * Send error message generated by 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, dev->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, 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 dcr->clear_reserved();
341 /* If failed and not writing plugin close device */
342 if (!ok && dev->num_writers == 0 && dev->num_reserved() == 0) {
343 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
346 * Normally we are blocked, but in at least one error case above
347 * we are not blocked because we unsuccessfully tried changing
350 if (dev->is_blocked()) {
351 dev->dunblock(DEV_LOCKED);
353 dev->Unlock(); /* dunblock() unlock the device too */
355 Dmsg2(rdbglvl, "dcr=%p dev=%p\n", dcr, dcr->dev);
356 Dmsg2(rdbglvl, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
357 dev->Unlock_read_acquire();
363 * Acquire device for writing. We permit multiple writers.
364 * If this is the first one, we read the label.
366 * Returns: NULL if failed for any reason
368 * Note, normally reserve_device_for_append() is called
369 * before this routine.
371 DCR *acquire_device_for_append(DCR *dcr)
373 DEVICE *dev = dcr->dev;
376 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->is_tape()?"tape":
384 (dev->is_dvd()?"DVD":"disk"));
386 * With the reservation system, this should not happen
388 if (dev->can_read()) {
389 Mmsg2(jcr->errmsg, "Want to append but %s device %s is busy reading.\n",
390 dev->print_type(), dev->print_name());
391 Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
392 Dmsg0(50, jcr->errmsg);
399 * have_vol defines whether or not mount_next_write_volume should
400 * ask the Director again about what Volume to use.
402 if (dev->can_append() && dcr->is_suitable_volume_mounted() &&
403 strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") != 0) {
404 Dmsg0(190, "device already in append.\n");
406 * At this point, the correct tape is already mounted, so
407 * we do not need to do mount_next_write_volume(), unless
408 * we need to recycle the tape.
410 if (dev->num_writers == 0) {
411 dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
413 have_vol = dcr->is_tape_position_ok();
418 block_device(dev, BST_DOING_ACQUIRE);
420 Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId);
421 if (!dcr->mount_next_write_volume()) {
422 if (!job_canceled(jcr)) {
423 /* Reduce "noise" -- don't print if job canceled */
424 Mmsg2(jcr->errmsg, _("Could not ready %s device %s for append.\n"),
425 dev->print_type(), dev->print_name());
426 Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
427 Dmsg0(50, jcr->errmsg);
433 Dmsg2(190, "Output pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num);
438 if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
439 Mmsg0(jcr->errmsg, _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
440 Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
441 Dmsg0(50, jcr->errmsg);
445 dev->num_writers++; /* we are now a writer */
446 if (jcr->NumWriteVolumes == 0) {
447 jcr->NumWriteVolumes = 1;
449 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */
450 Dmsg4(100, "=== nwriters=%d nres=%d vcatjob=%d dev=%s\n",
451 dev->num_writers, dev->num_reserved(), dev->VolCatInfo.VolCatJobs,
453 ok = dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
456 /* Don't plugin close here, we might have multiple writers */
457 dcr->clear_reserved();
459 dev->Unlock_acquire();
461 return ok ? dcr : NULL;
465 * This job is done, so release the device. From a Unix standpoint,
466 * the device remains open.
468 * Note, if we were spooling, we may enter with the device blocked.
469 * We unblock at the end, only if it was us who blocked the
473 bool release_device(DCR *dcr)
476 DEVICE *dev = dcr->dev;
479 int 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 Dmsg2(200, "dir_create_jobmedia. Release vol=%s dev=%s\n",
517 dev->getVolCatName(), dev->print_name());
518 if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
519 Jmsg2(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
520 dcr->getVolCatName(), jcr->Job);
522 /* If no more writers, and no errors, and wrote something, write an EOF */
523 if (!dev->num_writers && dev->can_write() && dev->block_num > 0) {
525 write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
527 if (!dev->at_weot()) {
528 dev->VolCatInfo.VolCatFiles = dev->get_file(); /* set number of files */
529 /* Note! do volume update before close, which zaps VolCatInfo */
530 dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
531 Dmsg2(200, "dir_update_vol_info. Release vol=%s dev=%s\n",
532 dev->getVolCatName(), dev->print_name());
534 if (dev->num_writers == 0) { /* if not being used */
535 volume_unused(dcr); /* we obviously are not using the volume */
536 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
542 * If we reach here, it is most likely because the job
543 * has failed, since the device is not in read mode and
544 * there are no writers. It was probably reserved.
547 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
549 Dmsg3(100, "%d writers, %d reserve, dev=%s\n", dev->num_writers, dev->num_reserved(),
552 /* If no writers, close if file or !CAP_ALWAYS_OPEN */
553 if (dev->num_writers == 0 && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
554 generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
556 Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
562 /* Fire off Alert command and include any output */
563 if (!job_canceled(jcr) && dcr->device->alert_command) {
567 char line[MAXSTRING];
568 alert = get_pool_memory(PM_FNAME);
569 alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
570 /* Wait maximum 5 minutes */
571 bpipe = open_bpipe(alert, 60 * 5, "r");
573 while (fgets(line, sizeof(line), bpipe->rfd)) {
574 Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
576 status = close_bpipe(bpipe);
582 Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
583 alert, be.bstrerror(status));
586 Dmsg1(400, "alert status=%d\n", status);
587 free_pool_memory(alert);
589 pthread_cond_broadcast(&dev->wait_next_vol);
590 Dmsg2(100, "JobId=%u broadcast wait_device_release at %s\n",
591 (uint32_t)jcr->JobId, bstrftimes(tbuf, sizeof(tbuf), (utime_t)time(NULL)));
592 pthread_cond_broadcast(&wait_device_release);
595 * If we are the thread that blocked the device, then unblock it
597 if (pthread_equal(dev->no_wait_id, pthread_self())) {
600 /* Otherwise, reset the prior block status and unlock */
601 dev->set_blocked(was_blocked);
606 dev->detach_dcr_from_dev(dcr);
610 Dmsg2(100, "Device %s released by JobId=%u\n", dev->print_name(),
611 (uint32_t)jcr->JobId);
616 * Clean up the device for reuse without freeing the memory
618 bool clean_device(DCR *dcr)
621 dcr->keep_dcr = true; /* do not free the dcr */
622 ok = release_device(dcr);
623 dcr->keep_dcr = false;
628 * Create a new Device Control Record and attach
629 * it to the device (if this is a real job).
630 * Note, this has been updated so that it can be called first
631 * without a DEVICE, then a second or third time with a DEVICE,
632 * and each time, it should cleanup and point to the new device.
633 * This should facilitate switching devices.
634 * Note, each dcr must point to the controlling job (jcr). However,
635 * a job can have multiple dcrs, so we must not store in the jcr's
636 * structure as previously. The higher level routine must store
637 * this dcr in the right place
640 DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev, bool writing)
644 dcr = (DCR *)malloc(sizeof(DCR));
645 memset(dcr, 0, sizeof(DCR));
646 dcr->tid = pthread_self();
649 dcr->jcr = jcr; /* point back to jcr */
651 if (dcr->attached_to_dev && odev) {
652 Dmsg2(100, "Detach 0x%x from olddev %s\n", dcr, odev->print_name());
653 odev->detach_dcr_from_dev(dcr);
655 ASSERT2(!dcr->attached_to_dev, "DCR is attached. Wrong!");
656 /* Set device information, possibly change device */
659 dcr->block = new_block(dev);
660 dcr->ameta_block = dcr->block;
662 free_record(dcr->rec);
664 dcr->rec = new_record();
665 /* Use job spoolsize prior to device spoolsize */
666 if (jcr && jcr->spool_size) {
667 dcr->max_job_spool_size = jcr->spool_size;
669 dcr->max_job_spool_size = dev->device->max_job_spool_size;
671 dcr->device = dev->device;
673 Dmsg2(100, "Attach 0x%x to dev %s\n", dcr, dev->print_name());
674 dev->attach_dcr_to_dev(dcr);
679 dcr->clear_writing();
685 * Search the dcrs list for the given dcr. If it is found,
686 * as it should be, then remove it. Also zap the jcr pointer
687 * to the dcr if it is the same one.
689 * Note, this code will be turned on when we can write to multiple
690 * dcrs at the same time.
693 static void remove_dcr_from_dcrs(DCR *dcr)
699 int num = jcr->dcrs->size();
700 for (i=0; i < num; i++) {
701 ldcr = (DCR *)jcr->dcrs->get(i);
703 jcr->dcrs->remove(i);
704 if (jcr->dcr == dcr) {
713 void DEVICE::attach_dcr_to_dev(DCR *dcr)
719 if (jcr) Dmsg1(500, "JobId=%u enter attach_dcr_to_dev\n", (uint32_t)jcr->JobId);
720 /* ***FIXME*** return error if dev not initiated */
721 if (!dcr->attached_to_dev && initiated && jcr && jcr->getJobType() != JT_SYSTEM) {
722 Dmsg4(200, "Attach Jid=%d dcr=%p size=%d dev=%s\n", (uint32_t)jcr->JobId,
723 dcr, attached_dcrs->size(), print_name());
724 attached_dcrs->append(dcr); /* attach dcr to device */
725 dcr->attached_to_dev = true;
731 * Note!! Do not enter with dev->Lock() since unreserve_device()
732 * is going to lock it too.
734 void DEVICE::detach_dcr_from_dev(DCR *dcr)
736 Dmsg0(500, "Enter detach_dcr_from_dev\n"); /* jcr is NULL in some cases */
740 /* Detach this dcr only if attached */
741 if (dcr->attached_to_dev) {
742 dcr->unreserve_device(true);
743 Dmsg4(200, "Detach Jid=%d dcr=%p size=%d to dev=%s\n", (uint32_t)dcr->jcr->JobId,
744 dcr, attached_dcrs->size(), print_name());
745 dcr->attached_to_dev = false;
746 if (attached_dcrs->size()) {
747 attached_dcrs->remove(dcr); /* detach dcr from device */
750 /* Check if someone accidentally left a drive reserved, and clear it */
751 if (attached_dcrs->size() == 0 && num_reserved() > 0) {
752 Pmsg2(000, "Warning!!! dcrs=0 reserved=%d setting reserved==0. dev=%s\n",
753 num_reserved(), print_name());
756 dcr->attached_to_dev = false;
762 * Free up all aspects of the given dcr -- i.e. dechain it,
763 * release allocated memory, zap pointers, ...
765 void free_dcr(DCR *dcr)
772 dcr->dev->detach_dcr_from_dev(dcr);
777 free_record(dcr->rec);
779 if (jcr && jcr->dcr == dcr) {
782 if (jcr && jcr->read_dcr == dcr) {
783 jcr->read_dcr = NULL;
788 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol)
791 * Note, if we want to be able to work from a .bsr file only
792 * for disaster recovery, we must "simulate" reading the catalog
794 bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
795 dcr->setVolCatName(vol->VolumeName);
796 bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
797 dcr->VolCatInfo.Slot = vol->Slot;
798 dcr->VolCatInfo.InChanger = vol->Slot > 0;