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 * Volume management functions for Storage Daemon
24 * Split from reserve.c October 2008
31 const int dbglvl = 150;
33 static dlist *vol_list = NULL;
34 static brwlock_t vol_list_lock;
35 static dlist *read_vol_list = NULL;
36 static bthread_mutex_t read_vol_lock = BTHREAD_MUTEX_PRIORITY(PRIO_SD_READ_VOL_LIST);
38 /* Forward referenced functions */
39 static void free_vol_item(VOLRES *vol);
40 static VOLRES *new_vol_item(DCR *dcr, const char *VolumeName);
41 static void debug_list_volumes(const char *imsg);
44 * For append volumes the key is the VolumeName.
46 static int name_compare(void *item1, void *item2)
48 return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
52 * For read volumes the key is JobId, VolumeName.
54 static int read_compare(void *item1, void *item2)
56 VOLRES *vol1 = (VOLRES *)item1;
57 VOLRES *vol2 = (VOLRES *)item2;
59 if (vol1->get_jobid() == vol2->get_jobid()) {
60 return strcmp(vol1->vol_name, vol2->vol_name);
62 if (vol1->get_jobid() < vol2->get_jobid()) {
68 bool is_vol_list_empty()
70 return vol_list->empty();
73 int vol_list_lock_count = 0;
76 * Initialized the main volume list. Note, we are using a recursive lock.
78 void init_vol_list_lock()
81 if ((errstat=rwl_init(&vol_list_lock, PRIO_SD_VOL_LIST)) != 0) {
83 Emsg1(M_ABORT, 0, _("Unable to initialize volume list lock. ERR=%s\n"),
84 be.bstrerror(errstat));
88 void term_vol_list_lock()
90 rwl_destroy(&vol_list_lock);
94 * This allows a given thread to recursively call to lock_volumes()
96 void _lock_volumes(const char *file, int line)
99 vol_list_lock_count++;
100 if ((errstat=rwl_writelock_p(&vol_list_lock, file, line)) != 0) {
102 Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
103 errstat, be.bstrerror(errstat));
107 void _unlock_volumes()
110 vol_list_lock_count--;
111 if ((errstat=rwl_writeunlock(&vol_list_lock)) != 0) {
113 Emsg2(M_ABORT, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
114 errstat, be.bstrerror(errstat));
118 #define lock_read_volumes() lock_read_volumes_p(__FILE__, __LINE__)
119 static void lock_read_volumes_p(const char *file="**Unknown", int line=0)
121 bthread_mutex_lock_p(&read_vol_lock, file, line);
124 static void unlock_read_volumes()
126 bthread_mutex_unlock(&read_vol_lock);
130 * Add a volume to the read list.
131 * Note, we use VOLRES because it simplifies the code
132 * even though, the only part of VOLRES that we need is
133 * the volume name. The same volume may be in the list
134 * multiple times, but each one is distinguished by the
135 * JobId. We use JobId, VolumeName as the key.
136 * We can get called multiple times for the same volume because
137 * when parsing the bsr, the volume name appears multiple times.
139 void add_read_volume(JCR *jcr, const char *VolumeName)
143 nvol = new_vol_item(NULL, VolumeName);
144 nvol->set_jobid(jcr->JobId);
147 vol = (VOLRES *)read_vol_list->binary_insert(nvol, read_compare);
150 Dmsg2(dbglvl, "read_vol=%s JobId=%d already in list.\n", VolumeName, jcr->JobId);
152 Dmsg2(dbglvl, "add read_vol=%s JobId=%d\n", VolumeName, jcr->JobId);
154 unlock_read_volumes();
158 * Check if volume name is in the read list.
160 bool is_read_volume(JCR *jcr, const char *VolumeName)
164 vol.vol_name = bstrdup(VolumeName);
165 fvol = (VOLRES *)read_vol_list->binary_search(&vol, name_compare);
167 unlock_read_volumes();
172 * Remove a given volume name from the read list.
174 void remove_read_volume(JCR *jcr, const char *VolumeName)
178 vol.vol_name = bstrdup(VolumeName);
179 vol.set_jobid(jcr->JobId);
180 fvol = (VOLRES *)read_vol_list->binary_search(&vol, read_compare);
183 Dmsg3(dbglvl, "remove_read_vol=%s JobId=%d found=%d\n", VolumeName, jcr->JobId, fvol!=NULL);
186 read_vol_list->remove(fvol);
189 unlock_read_volumes();
190 // pthread_cond_broadcast(&wait_next_vol);
194 * List Volumes -- this should be moved to status.c
201 static void debug_list_volumes(const char *imsg)
204 POOL_MEM msg(PM_MESSAGE);
206 if (debug_level < dbglvl) {
212 Mmsg(msg, "List %s: %s in_use=%d swap=%d slot=%d on %s device %s\n", imsg,
213 vol->vol_name, vol->is_in_use(), vol->is_swapping(),
215 vol->dev->print_type(), vol->dev->print_name());
217 Mmsg(msg, "List %s: %s in_use=%d swap=%d slot=%d no dev\n", imsg, vol->vol_name,
218 vol->is_in_use(), vol->is_swapping(), vol->get_slot());
220 Dmsg1(dbglvl, "%s", msg.c_str());
227 * List Volumes -- this should be moved to status.c
229 void list_volumes(void sendit(const char *msg, int len, void *sarg), void *arg)
232 POOL_MEM msg(PM_MESSAGE);
236 DEVICE *dev = vol->dev;
238 len = Mmsg(msg, "Reserved volume: %s on %s device %s\n", vol->vol_name,
239 dev->print_type(), dev->print_name());
240 sendit(msg.c_str(), len, arg);
241 len = Mmsg(msg, " Reader=%d writers=%d reserves=%d volinuse=%d\n",
242 dev->can_read()?1:0, dev->num_writers, dev->num_reserved(),
244 sendit(msg.c_str(), len, arg);
246 len = Mmsg(msg, "Volume %s no device. volinuse=%d\n", vol->vol_name,
248 sendit(msg.c_str(), len, arg);
254 foreach_dlist(vol, read_vol_list) {
255 DEVICE *dev = vol->dev;
257 len = Mmsg(msg, "Read volume: %s on %s device %s\n", vol->vol_name,
258 dev->print_type(), dev->print_name());
259 sendit(msg.c_str(), len, arg);
260 len = Mmsg(msg, " Reader=%d writers=%d reserves=%d volinuse=%d JobId=%d\n",
261 dev->can_read()?1:0, dev->num_writers, dev->num_reserved(),
262 vol->is_in_use(), vol->get_jobid());
263 sendit(msg.c_str(), len, arg);
265 len = Mmsg(msg, "Volume: %s no device. volinuse=%d\n", vol->vol_name,
267 sendit(msg.c_str(), len, arg);
270 unlock_read_volumes();
274 * Create a Volume item to put in the Volume list
275 * Ensure that the device points to it.
277 static VOLRES *new_vol_item(DCR *dcr, const char *VolumeName)
280 vol = (VOLRES *)malloc(sizeof(VOLRES));
281 memset(vol, 0, sizeof(VOLRES));
282 vol->vol_name = bstrdup(VolumeName);
285 Dmsg4(dbglvl, "new Vol=%s slot=%d at %p dev=%s\n",
286 VolumeName, vol->get_slot(), vol->vol_name, vol->dev->print_name());
289 vol->inc_use_count();
293 static void free_vol_item(VOLRES *vol)
297 vol->dec_use_count();
299 if (vol->use_count() > 0) {
308 vol->destroy_mutex();
316 * Put a new Volume entry in the Volume list. This
317 * effectively reserves the volume so that it will
318 * not be mounted again.
320 * If the device has any current volume associated with it,
321 * and it is a different Volume, and the device is not busy,
322 * we release the old Volume item and insert the new one.
324 * It is assumed that the device is free and locked so that
325 * we can change the device structure.
327 * Some details of the Volume list handling:
329 * 1. The Volume list entry is attached to the drive (rather than
330 * attached to a job as it was previously. I.e. the drive that "owns"
331 * the volume (in use, mounted)
332 * must point to the volume (still to be maintained in a list).
334 * 2. The Volume is entered in the list when a drive is reserved.
336 * 3. When a drive is in use, the device code must appropriately update the
337 * volume name as it changes.
338 * This code keeps the same list entry as long as the drive
339 * has any volume associated with it but the volume name in the list
340 * must be updated when the drive has a different volume mounted.
342 * 4. A job that has reserved a volume, can un-reserve the volume, and if the
343 * volume is not mounted, and not reserved, and not in use, it will be
344 * removed from the list.
346 * 5. If a job wants to reserve a drive with a different Volume from the one on
347 * the drive, it can re-use the drive for the new Volume.
349 * 6. If a job wants a Volume that is in a different drive, it can either use the
350 * other drive or take the volume, only if the other drive is not in use or
353 * One nice aspect of this is that the reserve use count and the writer use count
354 * already exist and are correctly programmed and will need no changes -- use
355 * counts are always very tricky.
357 * The old code had a concept of "reserving" a Volume, but was changed
358 * to reserving and using a drive. A volume is must be attached to (owned by) a
359 * drive and can move from drive to drive or be unused given certain specific
360 * conditions of the drive. The key is that the drive must "own" the Volume.
362 * Return: VOLRES entry on success
363 * NULL volume busy on another drive
364 * jcr->errmsg has details
366 VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
369 DEVICE * volatile dev = dcr->dev;
373 if (job_canceled(dcr->jcr)) {
374 Mmsg1(jcr->errmsg, _("Could not reserve volume \"%s\", because job canceled.\n"),
375 dev->VolHdr.VolumeName);
378 ASSERT2(dev != NULL, "No device in reserve_volume!");
380 Dmsg2(dbglvl, "enter reserve_volume=%s drive=%s\n", VolumeName,
381 dcr->dev->print_name());
383 /* If acquiring to write, don't accept a Volume in read list */
384 if (dcr->is_writing() && is_read_volume(dcr->jcr, VolumeName)) {
385 Mmsg1(jcr->errmsg, _("Could not reserve volume \"%s\" for append, because it will be read.\n"),
386 dev->VolHdr.VolumeName);
391 * We lock the reservations system here to ensure
392 * when adding a new volume that no newly scheduled
393 * job can reserve it.
396 debug_list_volumes("begin reserve_volume");
398 * First, remove any old volume attached to this device as it
403 Dmsg4(dbglvl, "Vol attached=%s, newvol=%s volinuse=%d on %s\n",
404 vol->vol_name, VolumeName, vol->is_in_use(), dev->print_name());
406 * Make sure we don't remove the current volume we are inserting
407 * because it was probably inserted by another job, or it
408 * is not being used and is marked as not reserved.
410 if (strcmp(vol->vol_name, VolumeName) == 0) {
411 Dmsg3(dbglvl, "set reserved vol=%s slot=%d dev=%s\n", VolumeName,
412 vol->get_slot(), vol->dev->print_name());
413 goto get_out; /* Volume already on this device */
415 /* Don't release a volume if it was reserved by someone other than us */
416 if (vol->is_in_use() && !dcr->reserved_volume) {
417 Dmsg2(dbglvl, "Set wait(). Cannot free vol=%s for %s. It is reserved.\n", vol->vol_name, VolumeName);
418 Mmsg1(dcr->jcr->errmsg, _("Cannot free Volume \"%s\", because it is reserved by someone else.\n"),
421 vol = NULL; /* vol in use */
424 Dmsg2(dbglvl, "reserve_vol free vol=%s at %p\n", vol->vol_name, vol->vol_name);
425 /* If old Volume is still mounted, must unload it */
426 if (strcmp(vol->vol_name, dev->VolHdr.VolumeName) == 0) {
427 Dmsg2(50, "set_unload vol=%s slot=%d\n", vol->vol_name, vol->get_slot());
428 dev->set_unload(); /* have to unload current volume */
430 free_volume(dev); /* Release old volume entry */
431 debug_list_volumes("reserve_vol free");
435 /* Create a new Volume entry */
436 nvol = new_vol_item(dcr, VolumeName);
439 * Handle request for read volume for file
440 * device, for which we assume we can open multiple
441 * devices to read the Volume.
443 * Note: when doing multiple simultaneous reads
444 * of the same volume, the volume names are not
445 * inserted into the write volume list.
447 if (dcr->is_reading() && dev->is_file()) {
448 nvol->set_jobid(dcr->jcr->JobId);
454 vol = (VOLRES *)vol_list->binary_insert(nvol, name_compare);
458 * This part handles any write volumes or read volumes that
459 * cannot be simultaneously on multiple devices.
463 * At this point, a Volume with this name already is in the list,
464 * so we simply release our new Volume entry. Note, this should
465 * only happen if we are moving the volume from one drive to another.
467 Dmsg2(dbglvl, "Found vol=%s dev-same=%d\n", vol->vol_name, dev==vol->dev);
468 Dmsg2(dbglvl, "reserve_vol free-tmp vol=%s at %p\n",
469 vol->vol_name, vol->vol_name);
471 * Clear dev pointer so that free_vol_item() doesn't
472 * take away our volume.
474 nvol->dev = NULL; /* don't zap dev entry */
478 Dmsg2(dbglvl, "dev=%s vol->dev=%s\n", dev->print_name(), vol->dev->print_name());
482 * Check if we are trying to use the Volume on a different drive
484 * vol->dev is where the Volume we want is
486 if (dev != vol->dev) {
487 /* Caller wants to switch Volume to another device */
488 if (!vol->dev->is_busy() && !vol->is_swapping()) {
490 Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n",
491 VolumeName, vol->dev->print_name(), dev->print_name());
492 free_volume(dev); /* free any volume attached to our drive */
493 Dmsg3(50, "set_unload vol=%s slot=%d dev=%s\n", vol->vol_name,
494 vol->get_slot(), dev->print_name());
495 dev->set_unload(); /* Unload any volume that is on our drive */
496 dcr->set_dev(vol->dev); /* temp point to other dev */
497 slot = get_autochanger_loaded_slot(dcr); /* get slot on other drive */
498 dcr->set_dev(dev); /* restore dev */
499 vol->set_slot(slot); /* save slot */
500 vol->dev->set_unload(); /* unload the other drive */
501 vol->set_swapping(); /* swap from other drive */
502 dev->swap_dev = vol->dev; /* remember to get this vol */
503 dev->set_load(); /* then reload on our drive */
504 vol->dev->vol = NULL; /* remove volume from other drive */
505 vol->dev = dev; /* point the Volume at our drive */
506 dev->vol = vol; /* point our drive at the Volume */
509 Jmsg8(jcr, M_WARNING, 0, "Need volume for %s from other drive, "
510 "but swap not possible. Status: reader=%d writers=%d "
511 "reserves=%d swap=%d vol=%s from dev=%s to %s\n",
512 dcr->is_writing()?"write":"read",
513 vol->dev->can_read(), vol->dev->num_writers,
514 vol->dev->num_reserved(), vol->is_swapping(),
515 VolumeName, vol->dev->print_name(), dev->print_name());
517 if (vol->is_swapping()) {
518 DEVICE *swapdev = dev->swap_dev;
519 if (vol && dev && swapdev) {
520 Mmsg3(jcr->errmsg, _("Volume %s is busy swapping from %s to %s\n"),
521 NPRT(vol->vol_name), dev->print_name(), swapdev->print_name());
523 Mmsg1(jcr->errmsg, _("Volume %s is busy swapping.\n"),
524 NPRT(vol->vol_name));
526 } else if (vol->dev) {
527 Mmsg2(jcr->errmsg, _("%s device %s is busy.\n"),
528 vol->dev->print_type(), vol->dev->print_name());
530 Mmsg1(jcr->errmsg, _("Volume %s is busy swapping.\n"),
531 NPRT(vol->vol_name));
533 debug_list_volumes("failed swap");
534 vol = NULL; /* device busy */
541 dev->vol = vol; /* point to newly inserted volume */
546 Dmsg2(dbglvl, "set in_use. vol=%s dev=%s\n", vol->vol_name,
547 vol->dev->print_name());
549 dcr->reserved_volume = true;
550 bstrncpy(dcr->VolumeName, vol->vol_name, sizeof(dcr->VolumeName));
552 debug_list_volumes("end new volume");
558 * Start walk of vol chain
559 * The proper way to walk the vol chain is:
566 * It is possible to leave out the endeach_vol(vol), but
567 * in that case, the last vol referenced must be explicitly
570 * free_vol_item(vol);
573 VOLRES *vol_walk_start()
577 vol = (VOLRES *)vol_list->first();
579 vol->inc_use_count();
580 Dmsg2(dbglvl, "Inc walk_start use_count=%d volname=%s\n",
581 vol->use_count(), vol->vol_name);
588 * Get next vol from chain, and release current one
590 VOLRES *vol_walk_next(VOLRES *prev_vol)
595 vol = (VOLRES *)vol_list->next(prev_vol);
597 vol->inc_use_count();
598 Dmsg2(dbglvl, "Inc walk_next use_count=%d volname=%s\n",
599 vol->use_count(), vol->vol_name);
602 free_vol_item(prev_vol);
609 * Release last vol referenced
611 void vol_walk_end(VOLRES *vol)
615 Dmsg2(dbglvl, "Free walk_end use_count=%d volname=%s\n",
616 vol->use_count(), vol->vol_name);
623 * Search for a Volume name in the Volume list.
625 * Returns: VOLRES entry on success
626 * NULL if the Volume is not in the list
628 static VOLRES *find_volume(const char *VolumeName)
632 if (vol_list->empty()) {
635 /* Do not lock reservations here */
637 vol.vol_name = bstrdup(VolumeName);
638 fvol = (VOLRES *)vol_list->binary_search(&vol, name_compare);
640 Dmsg2(dbglvl, "find_vol=%s found=%d\n", VolumeName, fvol!=NULL);
641 debug_list_volumes("find_volume");
647 * Search for a Volume name in the read Volume list.
649 * Returns: VOLRES entry on success
650 * NULL if the Volume is not in the list
652 static VOLRES *find_read_volume(const char *VolumeName)
656 if (read_vol_list->empty()) {
657 Dmsg0(dbglvl, "find_read_vol: read_vol_list empty.\n");
660 /* Do not lock reservations here */
662 vol.vol_name = bstrdup(VolumeName);
663 /* Note, we do want a simple name_compare on volume name only here */
664 fvol = (VOLRES *)read_vol_list->binary_search(&vol, name_compare);
666 Dmsg2(dbglvl, "find_read_vol=%s found=%d\n", VolumeName, fvol!=NULL);
667 unlock_read_volumes();
673 * Free a Volume from the Volume list if it is no longer used
674 * Note, for tape drives we want to remember where the Volume
675 * was when last used, so rather than free the volume entry,
676 * we simply mark it "not reserved" so when the drive is really
677 * needed for another volume, we can reuse it.
679 * Returns: true if the Volume found and "removed" from the list
680 * false if the Volume is not in the list or is in use
682 bool volume_unused(DCR *dcr)
684 DEVICE *dev = dcr->dev;
687 Dmsg1(dbglvl, "vol_unused: no vol on %s\n", dev->print_name());
688 debug_list_volumes("null vol cannot unreserve_volume");
692 Dmsg2(dbglvl, "Clear in_use vol=%s slot=%d\n", dev->vol->vol_name,
693 dev->vol->get_slot());
694 dev->vol->clear_in_use();
696 if (dev->vol->is_swapping()) {
697 Dmsg1(dbglvl, "vol_unused: vol being swapped on %s\n", dev->print_name());
698 debug_list_volumes("swapping vol cannot free_volume");
703 * If this is a tape, we do not free the volume, rather we wait
704 * until the autoloader unloads it, or until another tape is
705 * explicitly read in this drive. This allows the SD to remember
706 * where the tapes are or last were.
708 Dmsg5(dbglvl, "set not reserved vol=%s slot=%d writers=%d reserves=%d dev=%s\n",
709 dev->vol->vol_name, dev->vol->get_slot(), dev->num_writers,
710 dev->num_reserved(), dev->print_name());
711 if (dev->is_tape() || dev->is_autochanger()) {
715 * Note, this frees the volume reservation entry, but the
716 * file descriptor remains open with the OS.
718 return free_volume(dev);
723 * Unconditionally release the volume entry
724 * Note: read volumes are not in the list, so
725 * do not attempt to remove them.
727 bool free_volume(DEVICE *dev)
734 Dmsg1(dbglvl, "No vol on dev %s\n", dev->print_name());
738 /* Don't free a volume while it is being swapped */
739 if (!vol->is_swapping()) {
740 Dmsg2(dbglvl, "Clear in_use vol=%s slot=%d\n", vol->vol_name, vol->get_slot());
742 if (vol->is_writing()) {
743 vol_list->remove(vol);
745 Dmsg3(dbglvl, "Remove volume %s slot=%d dev=%s\n", vol->vol_name,
746 vol->get_slot(), dev->print_name());
748 debug_list_volumes("free_volume");
750 Dmsg1(dbglvl, "=== Cannot clear. Swapping vol=%s\n", vol->vol_name);
757 /* Create the Volume list */
758 void create_volume_lists()
761 if (vol_list == NULL) {
762 vol_list = New(dlist(vol, &vol->link));
764 if (read_vol_list == NULL) {
765 read_vol_list = New(dlist(vol, &vol->link));
770 * Free normal append volumes list
772 static void free_volume_list()
777 foreach_dlist(vol, vol_list) {
779 Dmsg2(dbglvl, "free vol_list Volume=%s dev=%s\n", vol->vol_name, vol->dev->print_name());
781 Dmsg1(dbglvl, "free vol_list Volume=%s No dev\n", vol->vol_name);
784 vol->vol_name = NULL;
785 vol->destroy_mutex();
793 /* Release all Volumes from the list */
794 void free_volume_lists()
798 free_volume_list(); /* normal append list */
802 foreach_dlist(vol, read_vol_list) {
804 Dmsg2(dbglvl, "free read_vol_list Volume=%s dev=%s\n", vol->vol_name, vol->dev->print_name());
806 Dmsg1(dbglvl, "free read_vol_list Volume=%s No dev\n", vol->vol_name);
809 vol->vol_name = NULL;
810 vol->destroy_mutex();
812 delete read_vol_list;
813 read_vol_list = NULL;
814 unlock_read_volumes();
819 * Determine if caller can write on volume.
820 * If not, return reason in jcr->errmsg
822 bool DCR::can_i_write_volume()
826 vol = find_read_volume(VolumeName);
828 Mmsg(jcr->errmsg, "Found in read list; cannot write vol=%s\n", VolumeName);
829 Dmsg1(100, "Found in read list; cannot write vol=%s\n", VolumeName);
832 return can_i_use_volume();
836 * Determine if caller can read or write volume.
837 * If not, return reason in jcr->errmsg
839 bool DCR::can_i_use_volume()
844 if (job_canceled(jcr)) {
845 Mmsg(jcr->errmsg, "Job is canceled\n");
849 vol = find_volume(VolumeName);
851 Dmsg1(dbglvl, "Vol=%s not in use.\n", VolumeName);
852 goto get_out; /* vol not in list */
854 ASSERT2(vol->dev != NULL, "No device in can_i_use_volume!");
856 if (dev == vol->dev) { /* same device OK */
857 Dmsg1(dbglvl, "Vol=%s on same dev.\n", VolumeName);
860 Dmsg3(dbglvl, "Vol=%s on %s we have %s\n", VolumeName,
861 vol->dev->print_name(), dev->print_name());
863 /* ***FIXME*** check this ... */
864 if (!vol->dev->is_busy()) {
865 Dmsg2(dbglvl, "Vol=%s dev=%s not busy.\n", VolumeName, vol->dev->print_name());
868 Dmsg2(dbglvl, "Vol=%s dev=%s busy.\n", VolumeName, vol->dev->print_name());
870 Mmsg(jcr->errmsg, "Volume=%s in use on another device %s.\n", VolumeName, vol->dev->print_name());
871 Dmsg2(dbglvl, "Volume=%s in use on another device %s.\n", VolumeName, vol->dev->print_name());
881 * Create a temporary copy of the volume list. We do this,
882 * to avoid having the volume list locked during the
883 * call to reserve_device(), which would cause a deadlock.
884 * Note, we may want to add an update counter on the vol_list
885 * so that if it is modified while we are traversing the copy
886 * we can take note and act accordingly (probably redo the
887 * search at least a few times).
889 dlist *dup_vol_list(JCR *jcr)
891 dlist *temp_vol_list;
894 Dmsg0(dbglvl, "lock volumes\n");
896 Dmsg0(dbglvl, "duplicate vol list\n");
897 temp_vol_list = New(dlist(vol, &vol->link));
900 VOLRES *tvol = (VOLRES *)malloc(sizeof(VOLRES));
901 memset(tvol, 0, sizeof(VOLRES));
902 tvol->vol_name = bstrdup(vol->vol_name);
903 tvol->dev = vol->dev;
905 tvol->inc_use_count();
906 nvol = (VOLRES *)temp_vol_list->binary_insert(tvol, name_compare);
908 tvol->dev = NULL; /* don't zap dev entry */
910 Pmsg0(000, "Logic error. Duplicating vol list hit duplicate.\n");
911 Jmsg(jcr, M_WARNING, 0, "Logic error. Duplicating vol list hit duplicate.\n");
915 Dmsg0(dbglvl, "unlock volumes\n");
916 return temp_vol_list;
920 * Free the specified temp list.
922 void free_temp_vol_list(dlist *temp_vol_list)
924 dlist *save_vol_list;
927 save_vol_list = vol_list;
928 vol_list = temp_vol_list;
929 free_volume_list(); /* release temp_vol_list */
930 vol_list = save_vol_list;
931 Dmsg0(dbglvl, "deleted temp vol list\n");
932 Dmsg0(dbglvl, "unlock volumes\n");
934 debug_list_volumes("after free temp table");