2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Drive reservation functions for Storage Daemon
33 * Split from job.c and acquire.c June 2005
42 const int dbglvl = 50;
44 static dlist *vol_list = NULL;
45 static brwlock_t reservation_lock;
46 static brwlock_t vol_list_lock;
48 /* Forward referenced functions */
49 static int can_reserve_drive(DCR *dcr, RCTX &rctx);
50 static int reserve_device(RCTX &rctx);
51 static bool reserve_device_for_read(DCR *dcr);
52 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
53 static bool use_storage_cmd(JCR *jcr);
54 static void queue_reserve_message(JCR *jcr);
55 static void pop_reserve_messages(JCR *jcr);
57 /* Requests from the Director daemon */
58 static char use_storage[] = "use storage=%127s media_type=%127s "
59 "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
60 static char use_device[] = "use device=%127s\n";
62 /* Responses sent to Director daemon */
63 static char OK_device[] = "3000 OK use device device=%s\n";
64 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
65 static char BAD_use[] = "3913 Bad use command: %s\n";
67 bool use_cmd(JCR *jcr)
70 * Get the device, media, and pool information
72 if (!use_storage_cmd(jcr)) {
73 set_jcr_job_status(jcr, JS_ErrorTerminated);
74 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
80 static int my_compare(void *item1, void *item2)
82 return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
86 void init_reservations_lock()
89 if ((errstat=rwl_init(&reservation_lock)) != 0) {
91 Emsg1(M_ABORT, 0, _("Unable to initialize reservation lock. ERR=%s\n"),
92 be.bstrerror(errstat));
95 if ((errstat=rwl_init(&vol_list_lock)) != 0) {
97 Emsg1(M_ABORT, 0, _("Unable to initialize volume list lock. ERR=%s\n"),
98 be.bstrerror(errstat));
102 void term_reservations_lock()
104 rwl_destroy(&reservation_lock);
105 rwl_destroy(&vol_list_lock);
108 int reservations_lock_count = 0;
110 /* This applies to a drive and to Volumes */
111 void _lock_reservations()
114 reservations_lock_count++;
115 if ((errstat=rwl_writelock(&reservation_lock)) != 0) {
117 Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
118 errstat, be.bstrerror(errstat));
122 void _unlock_reservations()
125 reservations_lock_count--;
126 if ((errstat=rwl_writeunlock(&reservation_lock)) != 0) {
128 Emsg2(M_ABORT, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
129 errstat, be.bstrerror(errstat));
133 int vol_list_lock_count = 0;
138 vol_list_lock_count++;
139 if ((errstat=rwl_writelock(&vol_list_lock)) != 0) {
141 Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
142 errstat, be.bstrerror(errstat));
146 void _unlock_volumes()
149 vol_list_lock_count--;
150 if ((errstat=rwl_writeunlock(&vol_list_lock)) != 0) {
152 Emsg2(M_ABORT, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
153 errstat, be.bstrerror(errstat));
159 * List Volumes -- this should be moved to status.c
166 static void debug_list_volumes(const char *imsg)
169 POOL_MEM msg(PM_MESSAGE);
172 foreach_dlist(vol, vol_list) {
174 Mmsg(msg, "List from %s: %s at %p on device %s\n", imsg,
175 vol->vol_name, vol->vol_name, vol->dev->print_name());
177 Mmsg(msg, "List from %s: %s at %p no dev\n", imsg, vol->vol_name, vol->vol_name);
179 Dmsg1(dbglvl, "%s", msg.c_str());
184 foreach_dlist(vol, vol_list) {
185 if (vol->dev == dev) {
186 Dmsg0(dbglvl, "Two Volumes on same device.\n");
193 // Dmsg2(dbglvl, "List from %s: %d volumes\n", imsg, count);
199 * List Volumes -- this should be moved to status.c
201 void list_volumes(void sendit(const char *msg, int len, void *sarg), void *arg)
204 POOL_MEM msg(PM_MESSAGE);
208 foreach_dlist(vol, vol_list) {
209 DEVICE *dev = vol->dev;
211 len = Mmsg(msg, "%s on device %s\n", vol->vol_name, dev->print_name());
212 sendit(msg.c_str(), len, arg);
213 len = Mmsg(msg, " Reader=%d writers=%d reserved=%d\n", dev->can_read()?1:0,
214 dev->num_writers, dev->reserved_device);
215 sendit(msg.c_str(), len, arg);
217 len = Mmsg(msg, "%s no dev\n", vol->vol_name);
218 sendit(msg.c_str(), len, arg);
225 * Create a Volume item to put in the Volume list
226 * Ensure that the device points to it.
228 static VOLRES *new_vol_item(DCR *dcr, const char *VolumeName)
231 vol = (VOLRES *)malloc(sizeof(VOLRES));
232 memset(vol, 0, sizeof(VOLRES));
233 vol->vol_name = bstrdup(VolumeName);
235 Dmsg3(dbglvl, "new Vol=%s at %p dev=%s\n",
236 VolumeName, vol->vol_name, vol->dev->print_name());
240 static void free_vol_item(VOLRES *vol)
244 vol->dev->vol = NULL;
251 * Put a new Volume entry in the Volume list. This
252 * effectively reserves the volume so that it will
253 * not be mounted again.
255 * If the device has any current volume associated with it,
256 * and it is a different Volume, and the device is not busy,
257 * we release the old Volume item and insert the new one.
259 * It is assumed that the device is free and locked so that
260 * we can change the device structure.
262 * Some details of the Volume list handling:
264 * 1. The Volume list entry must be attached to the drive (rather than
265 * attached to a job as it currently is. I.e. the drive that "owns"
266 * the volume (reserved, in use, mounted)
267 * must point to the volume (still to be maintained in a list).
269 * 2. The Volume is entered in the list when a drive is reserved.
271 * 3. When a drive is in use, the device code must appropriately update the
272 * volume name as it changes (currently the list is static -- an entry is
273 * removed when the Volume is no longer reserved, in use or mounted).
274 * The new code must keep the same list entry as long as the drive
275 * has any volume associated with it but the volume name in the list
276 * must be updated when the drive has a different volume mounted.
278 * 4. A job that has reserved a volume, can un-reserve the volume, and if the
279 * volume is not mounted, and not reserved, and not in use, it will be
280 * removed from the list.
282 * 5. If a job wants to reserve a drive with a different Volume from the one on
283 * the drive, it can re-use the drive for the new Volume.
285 * 6. If a job wants a Volume that is in a different drive, it can either use the
286 * other drive or take the volume, only if the other drive is not in use or
289 * One nice aspect of this is that the reserve use count and the writer use count
290 * already exist and are correctly programmed and will need no changes -- use
291 * counts are always very tricky.
293 * The old code had a concept of "reserving" a Volume, but was changed
294 * to reserving and using a drive. A volume is must be attached to (owned by) a
295 * drive and can move from drive to drive or be unused given certain specific
296 * conditions of the drive. The key is that the drive must "own" the Volume.
297 * The old code had the job (dcr) owning the volume (more or less). The job was
298 * to change the insertion and removal of the volumes from the list to be based
299 * on the drive rather than the job.
301 * Return: VOLRES entry on success
302 * NULL volume busy on another drive
304 VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
307 DEVICE *dev = dcr->dev;
311 Dmsg1(dbglvl, "reserve_volume %s\n", VolumeName);
313 * We lock the reservations system here to ensure
314 * when adding a new volume that no newly scheduled
315 * job can reserve it.
318 debug_list_volumes("begin reserve_volume");
320 * First, remove any old volume attached to this device as it
326 * Make sure we don't remove the current volume we are inserting
327 * because it was probably inserted by another job.
329 if (strcmp(vol->vol_name, VolumeName) == 0) {
330 Dmsg1(dbglvl, "OK, vol=%s on device.\n", VolumeName);
331 goto get_out; /* Volume already on this device */
333 Dmsg2(dbglvl, "reserve_vol free vol=%s at %p\n",
334 vol->vol_name, vol->vol_name);
335 debug_list_volumes("reserve_vol free");
336 vol_list->remove(vol);
341 /* Create a new Volume entry */
342 nvol = new_vol_item(dcr, VolumeName);
345 * Now try to insert the new Volume
347 vol = (VOLRES *)vol_list->binary_insert(nvol, my_compare);
349 Dmsg2(dbglvl, "Found vol=%s dev-same=%d\n", vol->vol_name, dev==vol->dev);
351 * At this point, a Volume with this name already is in the list,
352 * so we simply release our new Volume entry. Note, this should
353 * only happen if we are moving the volume from one drive to another.
355 Dmsg2(dbglvl, "reserve_vol free-tmp vol=%s at %p\n",
356 vol->vol_name, vol->vol_name);
358 * Clear dev pointer so that free_vol_item() doesn't
359 * take away our volume.
361 nvol->dev = NULL; /* don't zap dev entry */
364 /* Check if we are trying to use the Volume on a different drive */
365 if (dev != vol->dev) {
366 /* Caller wants to switch Volume to another device */
367 if (!vol->dev->is_busy()) {
368 /* OK to move it -- I'm not sure this will work */
369 Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n", VolumeName,
370 vol->dev->print_name(), dev->print_name());
371 vol->dev->vol = NULL; /* take vol from old drive */
372 vol->dev->VolHdr.VolumeName[0] = 0;
373 vol->dev = dev; /* point vol at new drive */
374 dev->vol = vol; /* point dev at vol */
375 dev->VolHdr.VolumeName[0] = 0;
377 Dmsg3(dbglvl, "Volume busy could not swap vol=%s from dev=%s to %s\n",
378 VolumeName, vol->dev->print_name(), dev->print_name());
379 vol = NULL; /* device busy */
386 debug_list_volumes("end new volume");
392 * Search for a Volume name in the Volume list.
394 * Returns: VOLRES entry on success
395 * NULL if the Volume is not in the list
397 VOLRES *find_volume(DCR *dcr)
400 /* Do not lock reservations here */
402 vol.vol_name = bstrdup(dcr->VolumeName);
403 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
405 Dmsg2(dbglvl, "find_vol=%s found=%d\n", dcr->VolumeName, fvol!=NULL);
406 debug_list_volumes("find_volume");
412 * Remove any reservation from a drive and tell the system
413 * that the volume is unused at least by us.
415 void unreserve_device(DCR *dcr)
417 DEVICE *dev = dcr->dev;
418 if (dcr->reserved_device) {
419 dcr->reserved_device = false;
420 dev->reserved_device--;
421 Dmsg2(dbglvl, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
422 dcr->reserved_device = false;
423 /* If we set read mode in reserving, remove it */
424 if (dev->can_read()) {
427 if (dev->num_writers < 0) {
428 Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
429 dev->num_writers = 0;
437 * Free a Volume from the Volume list if it is no longer used
439 * Returns: true if the Volume found and removed from the list
440 * false if the Volume is not in the list or is in use
442 bool volume_unused(DCR *dcr)
444 DEVICE *dev = dcr->dev;
446 if (dev->vol == NULL) {
447 Dmsg1(dbglvl, "vol_unused: no vol on %s\n", dev->print_name());
448 debug_list_volumes("null vol cannot unreserve_volume");
452 if (dev->is_busy()) {
453 Dmsg1(dbglvl, "vol_unused: no vol on %s\n", dev->print_name());
454 debug_list_volumes("dev busy cannot unreserve_volume");
459 * If this is a tape, we do not free the volume, rather we wait
460 * until the autoloader unloads it, or until another tape is
461 * explicitly read in this drive. This allows the SD to remember
462 * where the tapes are or last were.
464 if (dev->is_tape() || dev->is_autochanger()) {
467 return free_volume(dev);
472 * Unconditionally release the volume
474 bool free_volume(DEVICE *dev)
478 if (dev->vol == NULL) {
479 Dmsg1(dbglvl, "No vol on dev %s\n", dev->print_name());
485 vol_list->remove(vol);
486 Dmsg2(dbglvl, "free_volume %s dev=%s\n", vol->vol_name, dev->print_name());
488 debug_list_volumes("free_volume");
494 /* Create the Volume list */
495 void create_volume_list()
498 if (vol_list == NULL) {
499 vol_list = New(dlist(vol, &vol->link));
503 /* Release all Volumes from the list */
504 void free_volume_list()
511 foreach_dlist(vol, vol_list) {
513 Dmsg2(dbglvl, "free vol_list Volume=%s dev=%s\n", vol->vol_name, vol->dev->print_name());
515 Dmsg2(dbglvl, "free vol_list Volume=%s dev=%p\n", vol->vol_name, vol->dev);
518 vol->vol_name = NULL;
525 bool is_volume_in_use(DCR *dcr)
527 VOLRES *vol = find_volume(dcr);
529 Dmsg1(dbglvl, "Vol=%s not in use.\n", dcr->VolumeName);
530 return false; /* vol not in list */
532 ASSERT(vol->dev != NULL);
534 if (dcr->dev == vol->dev) { /* same device OK */
535 Dmsg1(dbglvl, "Vol=%s on same dev.\n", dcr->VolumeName);
538 Dmsg3(dbglvl, "Vol=%s on %s we have %s\n", dcr->VolumeName,
539 vol->dev->print_name(), dcr->dev->print_name());
541 if (!vol->dev->is_busy()) {
542 Dmsg2(dbglvl, "Vol=%s dev=%s not busy.\n", dcr->VolumeName, vol->dev->print_name());
545 Dmsg2(dbglvl, "Vol=%s dev=%s busy.\n", dcr->VolumeName, vol->dev->print_name());
547 Dmsg2(dbglvl, "Vol=%s in use by %s.\n", dcr->VolumeName, vol->dev->print_name());
553 * We get the following type of information:
555 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
559 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
563 static bool use_storage_cmd(JCR *jcr)
565 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
566 BSOCK *dir = jcr->dir_bsock;
574 memset(&rctx, 0, sizeof(RCTX));
577 * If there are multiple devices, the director sends us
578 * use_device for each device that it wants to use.
580 dirstore = New(alist(10, not_owned_by_alist));
581 jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
583 Dmsg1(dbglvl, "<dird: %s", dir->msg);
584 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
585 media_type.c_str(), pool_name.c_str(),
586 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
591 jcr->write_store = dirstore;
593 jcr->read_store = dirstore;
595 rctx.append = append;
596 unbash_spaces(store_name);
597 unbash_spaces(media_type);
598 unbash_spaces(pool_name);
599 unbash_spaces(pool_type);
600 store = new DIRSTORE;
601 dirstore->append(store);
602 memset(store, 0, sizeof(DIRSTORE));
603 store->device = New(alist(10));
604 bstrncpy(store->name, store_name, sizeof(store->name));
605 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
606 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
607 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
608 store->append = append;
610 /* Now get all devices */
611 while (dir->recv() >= 0) {
612 Dmsg1(dbglvl, "<dird device: %s", dir->msg);
613 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
617 unbash_spaces(dev_name);
618 store->device->append(bstrdup(dev_name.c_str()));
620 } while (ok && dir->recv() >= 0);
622 /* Developer debug code */
624 if (debug_level >= dbglvl) {
625 foreach_alist(store, dirstore) {
626 Dmsg5(dbglvl, "Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n",
627 store->name, store->media_type, store->pool_name,
628 store->pool_type, store->append);
629 foreach_alist(device_name, store->device) {
630 Dmsg1(dbglvl, " Device=%s\n", device_name);
635 init_jcr_device_wait_timers(jcr);
636 jcr->dcr = new_dcr(jcr, NULL, NULL); /* get a dcr */
638 BSOCK *dir = jcr->dir_bsock;
639 dir->fsend(_("3939 Could not get dcr\n"));
640 Dmsg1(dbglvl, ">dird: %s", dir->msg);
644 * At this point, we have a list of all the Director's Storage
645 * resources indicated for this Job, which include Pool, PoolType,
646 * storage name, and Media type.
647 * Then for each of the Storage resources, we have a list of
648 * device names that were given.
650 * Wiffle through them and find one that can do the backup.
653 int wait_for_device_retries = 0;
656 rctx.notify_dir = true;
659 for ( ; !fail && !job_canceled(jcr); ) {
660 pop_reserve_messages(jcr);
661 rctx.suitable_device = false;
662 rctx.have_volume = false;
663 rctx.VolumeName[0] = 0;
664 rctx.any_drive = false;
665 if (!jcr->PreferMountedVols) {
667 * Here we try to find a drive that is not used.
668 * This will maximize the use of available drives.
671 rctx.num_writers = 20000000; /* start with impossible number */
672 rctx.low_use_drive = NULL;
673 rctx.PreferMountedVols = false;
674 rctx.exact_match = false;
675 rctx.autochanger_only = true;
676 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
677 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
678 rctx.autochanger_only, rctx.any_drive);
679 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
682 /* Look through all drives possibly for low_use drive */
683 if (rctx.low_use_drive) {
684 rctx.try_low_use_drive = true;
685 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
688 rctx.try_low_use_drive = false;
690 rctx.autochanger_only = false;
691 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
692 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
693 rctx.autochanger_only, rctx.any_drive);
694 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
699 * Now we look for a drive that may or may not be in
702 /* Look for an exact Volume match all drives */
703 rctx.PreferMountedVols = true;
704 rctx.exact_match = true;
705 rctx.autochanger_only = false;
706 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
707 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
708 rctx.autochanger_only, rctx.any_drive);
709 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
712 /* Look for any mounted drive */
713 rctx.exact_match = false;
714 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
715 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
716 rctx.autochanger_only, rctx.any_drive);
717 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
721 rctx.any_drive = true;
722 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
723 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
724 rctx.autochanger_only, rctx.any_drive);
725 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
728 /* Keep reservations locked *except* during wait_for_device() */
729 unlock_reservations();
731 * The idea of looping on repeat a few times it to ensure
732 * that if there is some subtle timing problem between two
733 * jobs, we will simply try again, and most likely succeed.
734 * This can happen if one job reserves a drive or finishes using
735 * a drive at the same time a second job wants it.
737 if (repeat++ > 1) { /* try algorithm 3 times */
738 bmicrosleep(30, 0); /* wait a bit */
739 Dmsg0(dbglvl, "repeat reserve algorithm\n");
740 } else if (!rctx.suitable_device || !wait_for_device(jcr, wait_for_device_retries)) {
741 Dmsg0(dbglvl, "Fail. !suitable_device || !wait_for_device\n");
745 dir->signal(BNET_HEARTBEAT); /* Inform Dir that we are alive */
747 unlock_reservations();
750 * If we get here, there are no suitable devices available, which
751 * means nothing configured. If a device is suitable but busy
752 * with another Volume, we will not come here.
754 unbash_spaces(dir->msg);
755 pm_strcpy(jcr->errmsg, dir->msg);
756 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
757 Jmsg(jcr, M_FATAL, 0, _("\n"
758 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
759 dev_name.c_str(), media_type.c_str());
760 dir->fsend(NO_device, dev_name.c_str());
762 Dmsg1(dbglvl, ">dird: %s", dir->msg);
765 unbash_spaces(dir->msg);
766 pm_strcpy(jcr->errmsg, dir->msg);
767 Jmsg(jcr, M_FATAL, 0, _("Failed command: %s\n"), jcr->errmsg);
768 dir->fsend(BAD_use, jcr->errmsg);
769 Dmsg1(dbglvl, ">dird: %s", dir->msg);
772 release_reserve_messages(jcr);
778 * Walk through the autochanger resources and check if
779 * the volume is in one of them.
781 * Returns: true if volume is in device
784 static bool is_vol_in_autochanger(RCTX &rctx, VOLRES *vol)
786 AUTOCHANGER *changer = vol->dev->device->changer_res;
788 /* Find resource, and make sure we were able to open it */
789 if (strcmp(rctx.device_name, changer->hdr.name) == 0) {
790 Dmsg1(dbglvl, "Found changer device %s\n", vol->dev->device->hdr.name);
793 Dmsg1(dbglvl, "Incorrect changer device %s\n", changer->hdr.name);
798 * Search for a device suitable for this job.
800 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
809 dirstore = jcr->write_store;
811 dirstore = jcr->read_store;
813 Dmsg4(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
814 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
815 rctx.autochanger_only);
818 * If the appropriate conditions of this if are met, namely that
819 * we are appending and the user wants mounted drive (or we
820 * force try a mounted drive because they are all busy), we
821 * start by looking at all the Volumes in the volume list.
823 if (!vol_list->empty() && rctx.append && rctx.PreferMountedVols) {
824 dlist *temp_vol_list, *save_vol_list;
827 Dmsg0(dbglvl, "lock volumes\n");
830 * Create a temporary copy of the volume list. We do this,
831 * to avoid having the volume list locked during the
832 * call to reserve_device(), which would cause a deadlock.
833 * Note, we may want to add an update counter on the vol_list
834 * so that if it is modified while we are traversing the copy
835 * we can take note and act accordingly (probably redo the
836 * search at least a few times).
838 Dmsg0(dbglvl, "duplicate vol list\n");
839 temp_vol_list = New(dlist(vol, &vol->link));
840 foreach_dlist(vol, vol_list) {
842 VOLRES *tvol = (VOLRES *)malloc(sizeof(VOLRES));
843 memset(tvol, 0, sizeof(VOLRES));
844 tvol->vol_name = bstrdup(vol->vol_name);
845 tvol->dev = vol->dev;
846 nvol = (VOLRES *)temp_vol_list->binary_insert(tvol, my_compare);
848 tvol->dev = NULL; /* don't zap dev entry */
850 Pmsg0(000, "Logic error. Duplicating vol list hit duplicate.\n");
851 Jmsg(jcr, M_WARNING, 0, "Logic error. Duplicating vol list hit duplicate.\n");
854 Dmsg0(dbglvl, "unlock volumes\n");
857 /* Look through reserved volumes for one we can use */
858 Dmsg0(dbglvl, "look for vol in vol list\n");
859 foreach_dlist(vol, temp_vol_list) {
861 Dmsg1(dbglvl, "vol=%s no dev\n", vol->vol_name);
864 /* Check with Director if this Volume is OK */
865 bstrncpy(dcr->VolumeName, vol->vol_name, sizeof(dcr->VolumeName));
866 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) {
870 Dmsg1(dbglvl, "vol=%s OK for this job\n", vol->vol_name);
871 foreach_alist(store, dirstore) {
874 foreach_alist(device_name, store->device) {
875 /* Found a device, try to use it */
876 rctx.device_name = device_name;
877 rctx.device = vol->dev->device;
879 if (vol->dev->is_autochanger()) {
880 Dmsg1(dbglvl, "vol=%s is in changer\n", vol->vol_name);
881 if (!is_vol_in_autochanger(rctx, vol)) {
884 } else if (strcmp(device_name, vol->dev->device->hdr.name) != 0) {
885 Dmsg2(dbglvl, "device=%s not suitable want %s\n",
886 vol->dev->device->hdr.name, device_name);
890 bstrncpy(rctx.VolumeName, vol->vol_name, sizeof(rctx.VolumeName));
891 rctx.have_volume = true;
892 /* Try reserving this device and volume */
893 Dmsg2(dbglvl, "try vol=%s on device=%s\n", rctx.VolumeName, device_name);
894 stat = reserve_device(rctx);
895 if (stat == 1) { /* found available device */
896 Dmsg1(dbglvl, "Suitable device found=%s\n", device_name);
899 } else if (stat == 0) { /* device busy */
900 Dmsg1(dbglvl, "Suitable device=%s, busy: not use\n", device_name);
902 /* otherwise error */
903 Dmsg0(dbglvl, "No suitable device found.\n");
905 rctx.have_volume = false;
914 } /* end for loop over reserved volumes */
916 Dmsg0(dbglvl, "lock volumes\n");
918 save_vol_list = vol_list;
919 vol_list = temp_vol_list;
920 free_volume_list(); /* release temp_vol_list */
921 vol_list = save_vol_list;
922 Dmsg0(dbglvl, "deleted temp vol list\n");
923 Dmsg0(dbglvl, "lock volumes\n");
927 Dmsg1(dbglvl, "got vol %s from in-use vols list\n", rctx.VolumeName);
932 * No reserved volume we can use, so now search for an available device.
934 * For each storage device that the user specified, we
935 * search and see if there is a resource for that device.
937 foreach_alist(store, dirstore) {
939 foreach_alist(device_name, store->device) {
941 rctx.device_name = device_name;
942 stat = search_res_for_device(rctx);
943 if (stat == 1) { /* found available device */
944 Dmsg1(dbglvl, "available device found=%s\n", device_name);
947 } else if (stat == 0) { /* device busy */
948 Dmsg1(dbglvl, "Suitable device=%s, busy: not use\n", device_name);
950 /* otherwise error */
951 Dmsg0(dbglvl, "No suitable device found.\n");
962 * Search for a particular storage device with particular storage
963 * characteristics (MediaType).
965 int search_res_for_device(RCTX &rctx)
967 AUTOCHANGER *changer;
970 Dmsg1(dbglvl, "search res for %s\n", rctx.device_name);
971 /* Look through Autochangers first */
972 foreach_res(changer, R_AUTOCHANGER) {
973 Dmsg1(dbglvl, "Try match changer res=%s\n", changer->hdr.name);
974 /* Find resource, and make sure we were able to open it */
975 if (strcmp(rctx.device_name, changer->hdr.name) == 0) {
976 /* Try each device in this AutoChanger */
977 foreach_alist(rctx.device, changer->device) {
978 Dmsg1(dbglvl, "Try changer device %s\n", rctx.device->hdr.name);
979 stat = reserve_device(rctx);
980 if (stat != 1) { /* try another device */
984 if (rctx.store->append == SD_APPEND) {
985 Dmsg2(dbglvl, "Device %s reserved=%d for append.\n",
986 rctx.device->hdr.name, rctx.jcr->dcr->dev->reserved_device);
988 Dmsg2(dbglvl, "Device %s reserved=%d for read.\n",
989 rctx.device->hdr.name, rctx.jcr->read_dcr->dev->reserved_device);
996 /* Now if requested look through regular devices */
997 if (!rctx.autochanger_only) {
998 foreach_res(rctx.device, R_DEVICE) {
999 Dmsg1(dbglvl, "Try match res=%s\n", rctx.device->hdr.name);
1000 /* Find resource, and make sure we were able to open it */
1001 if (strcmp(rctx.device_name, rctx.device->hdr.name) == 0) {
1002 stat = reserve_device(rctx);
1003 if (stat != 1) { /* try another device */
1007 if (rctx.store->append == SD_APPEND) {
1008 Dmsg2(dbglvl, "Device %s reserved=%d for append.\n",
1009 rctx.device->hdr.name, rctx.jcr->dcr->dev->reserved_device);
1011 Dmsg2(dbglvl, "Device %s reserved=%d for read.\n",
1012 rctx.device->hdr.name, rctx.jcr->read_dcr->dev->reserved_device);
1018 return -1; /* nothing found */
1022 * Try to reserve a specific device.
1024 * Returns: 1 -- OK, have DCR
1028 static int reserve_device(RCTX &rctx)
1032 const int name_len = MAX_NAME_LENGTH;
1034 /* Make sure MediaType is OK */
1035 Dmsg2(dbglvl, "chk MediaType device=%s request=%s\n",
1036 rctx.device->media_type, rctx.store->media_type);
1037 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
1041 /* Make sure device exists -- i.e. we can stat() it */
1042 if (!rctx.device->dev) {
1043 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
1045 if (!rctx.device->dev) {
1046 if (rctx.device->changer_res) {
1047 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
1048 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
1049 rctx.device->hdr.name, rctx.device_name);
1051 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
1052 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
1055 return -1; /* no use waiting */
1058 rctx.suitable_device = true;
1059 Dmsg1(dbglvl, "try reserve %s\n", rctx.device->hdr.name);
1060 rctx.jcr->dcr = dcr = new_dcr(rctx.jcr, rctx.jcr->dcr, rctx.device->dev);
1062 BSOCK *dir = rctx.jcr->dir_bsock;
1063 dir->fsend(_("3926 Could not get dcr for device: %s\n"), rctx.device_name);
1064 Dmsg1(dbglvl, ">dird: %s", dir->msg);
1067 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
1068 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
1069 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
1070 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
1071 if (rctx.store->append == SD_APPEND) {
1072 Dmsg2(dbglvl, "have_vol=%d vol=%s\n", rctx.have_volume, rctx.VolumeName);
1073 ok = reserve_device_for_append(dcr, rctx);
1078 rctx.jcr->dcr = dcr;
1079 Dmsg5(dbglvl, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
1080 dcr->dev->reserved_device,
1081 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
1082 if (!rctx.have_volume) {
1083 dcr->any_volume = true;
1084 if (dir_find_next_appendable_volume(dcr)) {
1085 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
1086 Dmsg1(dbglvl, "looking for Volume=%s\n", rctx.VolumeName);
1087 rctx.have_volume = true;
1089 Dmsg0(dbglvl, "No next volume found\n");
1090 rctx.have_volume = false;
1091 rctx.VolumeName[0] = 0;
1093 * If there is at least one volume that is valid and in use,
1094 * but we get here, check if we are running with prefers
1095 * non-mounted drives. In that case, we have selected a
1096 * non-used drive and our one and only volume is mounted
1097 * elsewhere, so we bail out and retry using that drive.
1099 if (dcr->volume_in_use && !rctx.PreferMountedVols) {
1100 rctx.PreferMountedVols = true;
1101 if (dcr->VolumeName[0]) {
1107 * Note. Under some circumstances, the Director can hand us
1108 * a Volume name that is no the same as the one on the current
1109 * drive, and in that case, the call above to find the next
1110 * volume will fail because in attempting to reserve the Volume
1111 * the code will realize that we already have a tape mounted,
1112 * and it will fail. This *should* only happen if there are
1113 * writers, thus the following test. In that case, we simply
1114 * bail out, and continue waiting, rather than plunging on
1115 * and hoping that the operator can resolve the problem.
1117 if (dcr->dev->num_writers != 0) {
1118 if (dcr->VolumeName[0]) {
1126 ok = reserve_device_for_read(dcr);
1128 rctx.jcr->read_dcr = dcr;
1129 Dmsg5(dbglvl, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
1130 dcr->dev->reserved_device,
1131 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
1137 if (rctx.notify_dir) {
1139 BSOCK *dir = rctx.jcr->dir_bsock;
1140 pm_strcpy(dev_name, rctx.device->hdr.name);
1141 bash_spaces(dev_name);
1142 ok = dir->fsend(OK_device, dev_name.c_str()); /* Return real device name */
1143 Dmsg1(dbglvl, ">dird: %s", dir->msg);
1150 rctx.have_volume = false;
1152 Dmsg0(dbglvl, "Not OK.\n");
1157 * We "reserve" the drive by setting the ST_READ bit. No one else
1158 * should touch the drive until that is cleared.
1159 * This allows the DIR to "reserve" the device before actually
1162 static bool reserve_device_for_read(DCR *dcr)
1164 DEVICE *dev = dcr->dev;
1165 JCR *jcr = dcr->jcr;
1172 if (is_device_unmounted(dev)) {
1173 Dmsg1(dbglvl, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
1174 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
1175 jcr->JobId, dev->print_name());
1176 queue_reserve_message(jcr);
1180 if (dev->is_busy()) {
1181 Dmsg4(dbglvl, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n",
1183 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
1184 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
1185 jcr->JobId, dev->print_name());
1186 queue_reserve_message(jcr);
1190 dev->clear_append();
1193 dev->reserved_device++;
1194 Dmsg3(dbglvl, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, dev->print_name(), dev);
1195 dcr->reserved_device = true;
1204 * We reserve the device for appending by incrementing the
1205 * reserved_device. We do virtually all the same work that
1206 * is done in acquire_device_for_append(), but we do
1207 * not attempt to mount the device. This routine allows
1208 * the DIR to reserve multiple devices before *really*
1209 * starting the job. It also permits the SD to refuse
1210 * certain devices (not up, ...).
1212 * Note, in reserving a device, if the device is for the
1213 * same pool and the same pool type, then it is acceptable.
1214 * The Media Type has already been checked. If we are
1215 * the first tor reserve the device, we put the pool
1216 * name and pool type in the device record.
1218 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
1220 JCR *jcr = dcr->jcr;
1221 DEVICE *dev = dcr->dev;
1228 /* If device is being read, we cannot write it */
1229 if (dev->can_read()) {
1230 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
1231 jcr->JobId, dev->print_name());
1232 Dmsg1(dbglvl, "%s", jcr->errmsg);
1233 queue_reserve_message(jcr);
1237 /* If device is unmounted, we are out of luck */
1238 if (is_device_unmounted(dev)) {
1239 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
1240 jcr->JobId, dev->print_name());
1241 Dmsg1(dbglvl, "%s", jcr->errmsg);
1242 queue_reserve_message(jcr);
1246 Dmsg1(dbglvl, "reserve_append device is %s\n", dev->print_name());
1248 /* Now do detailed tests ... */
1249 if (can_reserve_drive(dcr, rctx) != 1) {
1250 Dmsg0(dbglvl, "can_reserve_drive!=1\n");
1254 dev->reserved_device++;
1255 Dmsg3(dbglvl, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
1256 dev->print_name(), dev);
1257 dcr->reserved_device = true;
1265 static int is_pool_ok(DCR *dcr)
1267 DEVICE *dev = dcr->dev;
1268 JCR *jcr = dcr->jcr;
1270 /* Now check if we want the same Pool and pool type */
1271 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1272 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1273 /* OK, compatible device */
1274 Dmsg1(dbglvl, "OK dev: %s num_writers=0, reserved, pool matches\n", dev->print_name());
1277 /* Drive Pool not suitable for us */
1278 Mmsg(jcr->errmsg, _(
1279 "3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"),
1280 jcr->JobId, dcr->pool_name, dev->pool_name,
1281 dev->reserved_device, dev->print_name());
1282 queue_reserve_message(jcr);
1283 Dmsg2(dbglvl, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
1284 dev->pool_name, dcr->pool_name);
1289 static bool is_max_jobs_ok(DCR *dcr)
1291 DEVICE *dev = dcr->dev;
1292 JCR *jcr = dcr->jcr;
1294 Dmsg4(dbglvl, "MaxJobs=%d Jobs=%d reserves=%d Vol=%s\n",
1295 dcr->VolCatInfo.VolCatMaxJobs,
1296 dcr->VolCatInfo.VolCatJobs, dev->reserved_device,
1298 if (dcr->VolCatInfo.VolCatMaxJobs > 0 && dcr->VolCatInfo.VolCatMaxJobs <=
1299 (dcr->VolCatInfo.VolCatJobs + dev->reserved_device)) {
1300 /* Max Job Vols depassed or already reserved */
1301 Mmsg(jcr->errmsg, _("3610 JobId=%u Volume max jobs exceeded on drive %s.\n"),
1302 (uint32_t)jcr->JobId, dev->print_name());
1303 queue_reserve_message(jcr);
1304 Dmsg1(dbglvl, "reserve dev failed: %s", jcr->errmsg);
1305 return false; /* wait */
1311 * Returns: 1 if drive can be reserved
1312 * 0 if we should wait
1313 * -1 on error or impossibility
1315 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
1317 DEVICE *dev = dcr->dev;
1318 JCR *jcr = dcr->jcr;
1320 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
1321 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1322 rctx.autochanger_only, rctx.any_drive);
1324 /* setting any_drive overrides PreferMountedVols flag */
1325 if (!rctx.any_drive) {
1327 * When PreferMountedVols is set, we keep track of the
1328 * drive in use that has the least number of writers, then if
1329 * no unmounted drive is found, we try that drive. This
1330 * helps spread the load to the least used drives.
1332 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
1333 Dmsg2(dbglvl, "OK dev=%s == low_drive=%s.\n",
1334 dev->print_name(), rctx.low_use_drive->print_name());
1337 /* If he wants a free drive, but this one is busy, no go */
1338 if (!rctx.PreferMountedVols && dev->is_busy()) {
1339 /* Save least used drive */
1340 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
1341 rctx.num_writers = dev->num_writers + dev->reserved_device;
1342 rctx.low_use_drive = dev;
1343 Dmsg2(dbglvl, "set low use drive=%s num_writers=%d\n",
1344 dev->print_name(), rctx.num_writers);
1346 Dmsg1(dbglvl, "not low use num_writers=%d\n", dev->num_writers+dev->reserved_device);
1348 Dmsg0(dbglvl, "failed: !prefMnt && busy.\n");
1349 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
1350 jcr->JobId, dev->print_name());
1351 queue_reserve_message(jcr);
1355 /* Check for prefer mounted volumes */
1356 if (rctx.PreferMountedVols && !dev->vol && dev->is_tape()) {
1357 Mmsg(jcr->errmsg, _("3606 JobId=%u prefers mounted drives, but drive %s has no Volume.\n"),
1358 jcr->JobId, dev->print_name());
1359 queue_reserve_message(jcr);
1360 Dmsg0(dbglvl, "failed: want mounted -- no vol\n");
1361 return 0; /* No volume mounted */
1364 /* Check for exact Volume name match */
1365 /* ***FIXME*** for Disk, we can accept any volume that goes with this
1368 if (rctx.exact_match && rctx.have_volume) {
1370 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
1371 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1372 rctx.autochanger_only, rctx.any_drive);
1373 Dmsg4(dbglvl, "have_vol=%d have=%s resvol=%s want=%s\n",
1374 rctx.have_volume, dev->VolHdr.VolumeName,
1375 dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName);
1376 ok = strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) == 0 ||
1377 (dev->vol && strcmp(dev->vol->vol_name, rctx.VolumeName) == 0);
1379 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
1380 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
1382 queue_reserve_message(jcr);
1383 Dmsg3(dbglvl, "not OK: dev have=%s resvol=%s want=%s\n",
1384 dev->VolHdr.VolumeName, dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName);
1387 if (is_volume_in_use(dcr)) {
1388 return 0; /* fail if volume on another drive */
1393 /* Check for unused autochanger drive */
1394 if (rctx.autochanger_only && !dev->is_busy() &&
1395 dev->VolHdr.VolumeName[0] == 0) {
1396 /* Device is available but not yet reserved, reserve it for us */
1397 Dmsg1(dbglvl, "OK Res Unused autochanger %s.\n", dev->print_name());
1398 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1399 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1400 return 1; /* reserve drive */
1404 * Handle the case that there are no writers
1406 if (dev->num_writers == 0) {
1407 /* Now check if there are any reservations on the drive */
1408 if (dev->reserved_device) {
1409 if (!is_max_jobs_ok(dcr)) {
1412 return is_pool_ok(dcr);
1413 } else if (dev->can_append()) {
1414 if (is_pool_ok(dcr)) {
1417 /* Changing pool, unload old tape if any in drive */
1418 Dmsg0(dbglvl, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
1419 unload_autochanger(dcr, 0);
1422 /* Device is available but not yet reserved, reserve it for us */
1423 Dmsg1(dbglvl, "OK Dev avail reserved %s\n", dev->print_name());
1424 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1425 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1426 return 1; /* reserve drive */
1430 * Check if the device is in append mode with writers (i.e.
1431 * available if pool is the same).
1433 if (dev->can_append() || dev->num_writers > 0) {
1434 if (!is_max_jobs_ok(dcr)) {
1437 return is_pool_ok(dcr);
1439 Pmsg1(000, _("Logic error!!!! JobId=%u Should not get here.\n"), (int)jcr->JobId);
1440 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
1441 jcr->JobId, dev->print_name());
1442 queue_reserve_message(jcr);
1443 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
1444 return -1; /* error, should not get here */
1446 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
1447 jcr->JobId, dev->print_name());
1448 queue_reserve_message(jcr);
1449 Dmsg1(dbglvl, "failed: No reserve %s\n", dev->print_name());
1457 * Queue a reservation error or failure message for this jcr
1459 static void queue_reserve_message(JCR *jcr)
1467 msgs = jcr->reserve_msgs;
1472 * Look for duplicate message. If found, do
1475 for (i=msgs->size()-1; i >= 0; i--) {
1476 msg = (char *)msgs->get(i);
1480 /* Comparison based on 4 digit message number */
1481 if (strncmp(msg, jcr->errmsg, 4) == 0) {
1485 /* Message unique, so insert it */
1486 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1493 * Send any reservation messages queued for this jcr
1495 void send_drive_reserve_messages(JCR *jcr, void sendit(const char *msg, int len, void *sarg), void *arg)
1502 msgs = jcr->reserve_msgs;
1503 if (!msgs || msgs->size() == 0) {
1506 for (i=msgs->size()-1; i >= 0; i--) {
1507 msg = (char *)msgs->get(i);
1509 sendit(" ", 3, arg);
1510 sendit(msg, strlen(msg), arg);
1521 * Pop and release any reservations messages
1523 static void pop_reserve_messages(JCR *jcr)
1529 msgs = jcr->reserve_msgs;
1533 while ((msg = (char *)msgs->pop())) {
1541 * Also called from acquire.c
1543 void release_reserve_messages(JCR *jcr)
1545 pop_reserve_messages(jcr);
1547 if (!jcr->reserve_msgs) {
1550 delete jcr->reserve_msgs;
1551 jcr->reserve_msgs = NULL;