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 released=%d\n",
214 dev->can_read()?1:0, dev->num_writers, dev->reserved_device, vol->released);
215 sendit(msg.c_str(), len, arg);
217 len = Mmsg(msg, "%s no device. released=%d\n", vol->vol_name, vol->released);
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", vol->vol_name, vol->vol_name);
334 vol_list->remove(vol);
336 debug_list_volumes("reserve_vol free");
340 /* Create a new Volume entry */
341 nvol = new_vol_item(dcr, VolumeName);
344 * Now try to insert the new Volume
346 vol = (VOLRES *)vol_list->binary_insert(nvol, my_compare);
348 Dmsg2(dbglvl, "Found vol=%s dev-same=%d\n", vol->vol_name, dev==vol->dev);
350 * At this point, a Volume with this name already is in the list,
351 * so we simply release our new Volume entry. Note, this should
352 * only happen if we are moving the volume from one drive to another.
354 Dmsg2(dbglvl, "reserve_vol free-tmp vol=%s at %p\n",
355 vol->vol_name, vol->vol_name);
357 * Clear dev pointer so that free_vol_item() doesn't
358 * take away our volume.
360 nvol->dev = NULL; /* don't zap dev entry */
363 /* Check if we are trying to use the Volume on a different drive */
364 if (dev != vol->dev) {
365 /* Caller wants to switch Volume to another device */
366 if (!vol->dev->is_busy()) {
367 /* OK to move it -- I'm not sure this will work */
368 Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n", VolumeName,
369 vol->dev->print_name(), dev->print_name());
370 vol->dev->vol = NULL; /* take vol from old drive */
371 vol->dev->VolHdr.VolumeName[0] = 0;
372 vol->dev = dev; /* point vol at new drive */
373 dev->vol = vol; /* point dev at vol */
374 dev->VolHdr.VolumeName[0] = 0;
376 Dmsg3(dbglvl, "Volume busy could not swap vol=%s from dev=%s to %s\n",
377 VolumeName, vol->dev->print_name(), dev->print_name());
378 vol = NULL; /* device busy */
387 vol->released = false;
389 debug_list_volumes("end new volume");
395 * Search for a Volume name in the Volume list.
397 * Returns: VOLRES entry on success
398 * NULL if the Volume is not in the list
400 VOLRES *find_volume(DCR *dcr)
403 /* Do not lock reservations here */
405 vol.vol_name = bstrdup(dcr->VolumeName);
406 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
408 Dmsg2(dbglvl, "find_vol=%s found=%d\n", dcr->VolumeName, fvol!=NULL);
409 debug_list_volumes("find_volume");
415 * Remove any reservation from a drive and tell the system
416 * that the volume is unused at least by us.
418 void unreserve_device(DCR *dcr)
420 DEVICE *dev = dcr->dev;
421 if (dcr->reserved_device) {
422 dcr->reserved_device = false;
423 dev->reserved_device--;
424 Dmsg2(dbglvl, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
425 dcr->reserved_device = false;
426 /* If we set read mode in reserving, remove it */
427 if (dev->can_read()) {
430 if (dev->num_writers < 0) {
431 Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
432 dev->num_writers = 0;
440 * Free a Volume from the Volume list if it is no longer used
442 * Returns: true if the Volume found and removed from the list
443 * false if the Volume is not in the list or is in use
445 bool volume_unused(DCR *dcr)
447 DEVICE *dev = dcr->dev;
449 if (dev->vol == NULL) {
450 Dmsg1(dbglvl, "vol_unused: no vol on %s\n", dev->print_name());
451 debug_list_volumes("null vol cannot unreserve_volume");
455 if (dev->is_busy()) {
456 Dmsg1(dbglvl, "vol_unused: busy on %s\n", dev->print_name());
457 debug_list_volumes("dev busy cannot unreserve_volume");
462 * If this is a tape, we do not free the volume, rather we wait
463 * until the autoloader unloads it, or until another tape is
464 * explicitly read in this drive. This allows the SD to remember
465 * where the tapes are or last were.
467 dev->vol->released = true;
468 if (dev->is_tape() || dev->is_autochanger()) {
471 return free_volume(dev);
476 * Unconditionally release the volume
478 bool free_volume(DEVICE *dev)
482 if (dev->vol == NULL) {
483 Dmsg1(dbglvl, "No vol on dev %s\n", dev->print_name());
489 vol_list->remove(vol);
490 Dmsg2(dbglvl, "free_volume %s dev=%s\n", vol->vol_name, dev->print_name());
492 debug_list_volumes("free_volume");
498 /* Create the Volume list */
499 void create_volume_list()
502 if (vol_list == NULL) {
503 vol_list = New(dlist(vol, &vol->link));
507 /* Release all Volumes from the list */
508 void free_volume_list()
515 foreach_dlist(vol, vol_list) {
517 Dmsg2(dbglvl, "free vol_list Volume=%s dev=%s\n", vol->vol_name, vol->dev->print_name());
519 Dmsg1(dbglvl, "free vol_list Volume=%s No dev\n", vol->vol_name);
522 vol->vol_name = NULL;
529 bool is_volume_in_use(DCR *dcr)
531 VOLRES *vol = find_volume(dcr);
533 Dmsg1(dbglvl, "Vol=%s not in use.\n", dcr->VolumeName);
534 return false; /* vol not in list */
536 ASSERT(vol->dev != NULL);
538 if (dcr->dev == vol->dev) { /* same device OK */
539 Dmsg1(dbglvl, "Vol=%s on same dev.\n", dcr->VolumeName);
542 Dmsg3(dbglvl, "Vol=%s on %s we have %s\n", dcr->VolumeName,
543 vol->dev->print_name(), dcr->dev->print_name());
545 if (!vol->dev->is_busy()) {
546 Dmsg2(dbglvl, "Vol=%s dev=%s not busy.\n", dcr->VolumeName, vol->dev->print_name());
549 Dmsg2(dbglvl, "Vol=%s dev=%s busy.\n", dcr->VolumeName, vol->dev->print_name());
551 Dmsg2(dbglvl, "Vol=%s in use by %s.\n", dcr->VolumeName, vol->dev->print_name());
557 * We get the following type of information:
559 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
563 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
567 static bool use_storage_cmd(JCR *jcr)
569 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
570 BSOCK *dir = jcr->dir_bsock;
578 memset(&rctx, 0, sizeof(RCTX));
581 * If there are multiple devices, the director sends us
582 * use_device for each device that it wants to use.
584 dirstore = New(alist(10, not_owned_by_alist));
585 jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
587 Dmsg1(dbglvl, "<dird: %s", dir->msg);
588 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
589 media_type.c_str(), pool_name.c_str(),
590 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
595 jcr->write_store = dirstore;
597 jcr->read_store = dirstore;
599 rctx.append = append;
600 unbash_spaces(store_name);
601 unbash_spaces(media_type);
602 unbash_spaces(pool_name);
603 unbash_spaces(pool_type);
604 store = new DIRSTORE;
605 dirstore->append(store);
606 memset(store, 0, sizeof(DIRSTORE));
607 store->device = New(alist(10));
608 bstrncpy(store->name, store_name, sizeof(store->name));
609 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
610 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
611 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
612 store->append = append;
614 /* Now get all devices */
615 while (dir->recv() >= 0) {
616 Dmsg1(dbglvl, "<dird device: %s", dir->msg);
617 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
621 unbash_spaces(dev_name);
622 store->device->append(bstrdup(dev_name.c_str()));
624 } while (ok && dir->recv() >= 0);
626 /* Developer debug code */
628 if (debug_level >= dbglvl) {
629 foreach_alist(store, dirstore) {
630 Dmsg5(dbglvl, "Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n",
631 store->name, store->media_type, store->pool_name,
632 store->pool_type, store->append);
633 foreach_alist(device_name, store->device) {
634 Dmsg1(dbglvl, " Device=%s\n", device_name);
639 init_jcr_device_wait_timers(jcr);
640 jcr->dcr = new_dcr(jcr, NULL, NULL); /* get a dcr */
642 BSOCK *dir = jcr->dir_bsock;
643 dir->fsend(_("3939 Could not get dcr\n"));
644 Dmsg1(dbglvl, ">dird: %s", dir->msg);
648 * At this point, we have a list of all the Director's Storage
649 * resources indicated for this Job, which include Pool, PoolType,
650 * storage name, and Media type.
651 * Then for each of the Storage resources, we have a list of
652 * device names that were given.
654 * Wiffle through them and find one that can do the backup.
657 int wait_for_device_retries = 0;
660 rctx.notify_dir = true;
663 for ( ; !fail && !job_canceled(jcr); ) {
664 pop_reserve_messages(jcr);
665 rctx.suitable_device = false;
666 rctx.have_volume = false;
667 rctx.VolumeName[0] = 0;
668 rctx.any_drive = false;
669 if (!jcr->PreferMountedVols) {
671 * Here we try to find a drive that is not used.
672 * This will maximize the use of available drives.
675 rctx.num_writers = 20000000; /* start with impossible number */
676 rctx.low_use_drive = NULL;
677 rctx.PreferMountedVols = false;
678 rctx.exact_match = false;
679 rctx.autochanger_only = true;
680 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
681 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
682 rctx.autochanger_only, rctx.any_drive);
683 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
686 /* Look through all drives possibly for low_use drive */
687 if (rctx.low_use_drive) {
688 rctx.try_low_use_drive = true;
689 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
692 rctx.try_low_use_drive = false;
694 rctx.autochanger_only = false;
695 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
696 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
697 rctx.autochanger_only, rctx.any_drive);
698 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
703 * Now we look for a drive that may or may not be in
706 /* Look for an exact Volume match all drives */
707 rctx.PreferMountedVols = true;
708 rctx.exact_match = true;
709 rctx.autochanger_only = false;
710 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
711 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
712 rctx.autochanger_only, rctx.any_drive);
713 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
716 /* Look for any mounted drive */
717 rctx.exact_match = false;
718 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
719 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
720 rctx.autochanger_only, rctx.any_drive);
721 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
725 rctx.any_drive = true;
726 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
727 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
728 rctx.autochanger_only, rctx.any_drive);
729 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
732 /* Keep reservations locked *except* during wait_for_device() */
733 unlock_reservations();
735 * The idea of looping on repeat a few times it to ensure
736 * that if there is some subtle timing problem between two
737 * jobs, we will simply try again, and most likely succeed.
738 * This can happen if one job reserves a drive or finishes using
739 * a drive at the same time a second job wants it.
741 if (repeat++ > 1) { /* try algorithm 3 times */
742 bmicrosleep(30, 0); /* wait a bit */
743 Dmsg0(dbglvl, "repeat reserve algorithm\n");
744 } else if (!rctx.suitable_device || !wait_for_device(jcr, wait_for_device_retries)) {
745 Dmsg0(dbglvl, "Fail. !suitable_device || !wait_for_device\n");
749 dir->signal(BNET_HEARTBEAT); /* Inform Dir that we are alive */
751 unlock_reservations();
754 * If we get here, there are no suitable devices available, which
755 * means nothing configured. If a device is suitable but busy
756 * with another Volume, we will not come here.
758 unbash_spaces(dir->msg);
759 pm_strcpy(jcr->errmsg, dir->msg);
760 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
761 Jmsg(jcr, M_FATAL, 0, _("\n"
762 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
763 dev_name.c_str(), media_type.c_str());
764 dir->fsend(NO_device, dev_name.c_str());
766 Dmsg1(dbglvl, ">dird: %s", dir->msg);
769 unbash_spaces(dir->msg);
770 pm_strcpy(jcr->errmsg, dir->msg);
771 Jmsg(jcr, M_FATAL, 0, _("Failed command: %s\n"), jcr->errmsg);
772 dir->fsend(BAD_use, jcr->errmsg);
773 Dmsg1(dbglvl, ">dird: %s", dir->msg);
776 release_reserve_messages(jcr);
782 * Walk through the autochanger resources and check if
783 * the volume is in one of them.
785 * Returns: true if volume is in device
788 static bool is_vol_in_autochanger(RCTX &rctx, VOLRES *vol)
790 AUTOCHANGER *changer = vol->dev->device->changer_res;
792 /* Find resource, and make sure we were able to open it */
793 if (strcmp(rctx.device_name, changer->hdr.name) == 0) {
794 Dmsg1(dbglvl, "Found changer device %s\n", vol->dev->device->hdr.name);
797 Dmsg1(dbglvl, "Incorrect changer device %s\n", changer->hdr.name);
802 * Search for a device suitable for this job.
804 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
813 dirstore = jcr->write_store;
815 dirstore = jcr->read_store;
817 Dmsg4(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
818 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
819 rctx.autochanger_only);
822 * If the appropriate conditions of this if are met, namely that
823 * we are appending and the user wants mounted drive (or we
824 * force try a mounted drive because they are all busy), we
825 * start by looking at all the Volumes in the volume list.
827 if (!vol_list->empty() && rctx.append && rctx.PreferMountedVols) {
828 dlist *temp_vol_list, *save_vol_list;
831 Dmsg0(dbglvl, "lock volumes\n");
834 * Create a temporary copy of the volume list. We do this,
835 * to avoid having the volume list locked during the
836 * call to reserve_device(), which would cause a deadlock.
837 * Note, we may want to add an update counter on the vol_list
838 * so that if it is modified while we are traversing the copy
839 * we can take note and act accordingly (probably redo the
840 * search at least a few times).
842 Dmsg0(dbglvl, "duplicate vol list\n");
843 temp_vol_list = New(dlist(vol, &vol->link));
844 foreach_dlist(vol, vol_list) {
846 VOLRES *tvol = (VOLRES *)malloc(sizeof(VOLRES));
847 memset(tvol, 0, sizeof(VOLRES));
848 tvol->vol_name = bstrdup(vol->vol_name);
849 tvol->dev = vol->dev;
850 nvol = (VOLRES *)temp_vol_list->binary_insert(tvol, my_compare);
852 tvol->dev = NULL; /* don't zap dev entry */
854 Pmsg0(000, "Logic error. Duplicating vol list hit duplicate.\n");
855 Jmsg(jcr, M_WARNING, 0, "Logic error. Duplicating vol list hit duplicate.\n");
858 Dmsg0(dbglvl, "unlock volumes\n");
861 /* Look through reserved volumes for one we can use */
862 Dmsg0(dbglvl, "look for vol in vol list\n");
863 foreach_dlist(vol, temp_vol_list) {
865 Dmsg1(dbglvl, "vol=%s no dev\n", vol->vol_name);
868 /* Check with Director if this Volume is OK */
869 bstrncpy(dcr->VolumeName, vol->vol_name, sizeof(dcr->VolumeName));
870 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) {
874 Dmsg1(dbglvl, "vol=%s OK for this job\n", vol->vol_name);
875 foreach_alist(store, dirstore) {
878 foreach_alist(device_name, store->device) {
879 /* Found a device, try to use it */
880 rctx.device_name = device_name;
881 rctx.device = vol->dev->device;
883 if (vol->dev->is_autochanger()) {
884 Dmsg1(dbglvl, "vol=%s is in changer\n", vol->vol_name);
885 if (!is_vol_in_autochanger(rctx, vol)) {
888 } else if (strcmp(device_name, vol->dev->device->hdr.name) != 0) {
889 Dmsg2(dbglvl, "device=%s not suitable want %s\n",
890 vol->dev->device->hdr.name, device_name);
894 bstrncpy(rctx.VolumeName, vol->vol_name, sizeof(rctx.VolumeName));
895 rctx.have_volume = true;
896 /* Try reserving this device and volume */
897 Dmsg2(dbglvl, "try vol=%s on device=%s\n", rctx.VolumeName, device_name);
898 stat = reserve_device(rctx);
899 if (stat == 1) { /* found available device */
900 Dmsg1(dbglvl, "Suitable device found=%s\n", device_name);
903 } else if (stat == 0) { /* device busy */
904 Dmsg1(dbglvl, "Suitable device=%s, busy: not use\n", device_name);
906 /* otherwise error */
907 Dmsg0(dbglvl, "No suitable device found.\n");
909 rctx.have_volume = false;
918 } /* end for loop over reserved volumes */
920 Dmsg0(dbglvl, "lock volumes\n");
922 save_vol_list = vol_list;
923 vol_list = temp_vol_list;
924 free_volume_list(); /* release temp_vol_list */
925 vol_list = save_vol_list;
926 Dmsg0(dbglvl, "deleted temp vol list\n");
927 Dmsg0(dbglvl, "lock volumes\n");
931 Dmsg1(dbglvl, "got vol %s from in-use vols list\n", rctx.VolumeName);
936 * No reserved volume we can use, so now search for an available device.
938 * For each storage device that the user specified, we
939 * search and see if there is a resource for that device.
941 foreach_alist(store, dirstore) {
943 foreach_alist(device_name, store->device) {
945 rctx.device_name = device_name;
946 stat = search_res_for_device(rctx);
947 if (stat == 1) { /* found available device */
948 Dmsg1(dbglvl, "available device found=%s\n", device_name);
951 } else if (stat == 0) { /* device busy */
952 Dmsg1(dbglvl, "Suitable device=%s, busy: not use\n", device_name);
954 /* otherwise error */
955 Dmsg0(dbglvl, "No suitable device found.\n");
966 * Search for a particular storage device with particular storage
967 * characteristics (MediaType).
969 int search_res_for_device(RCTX &rctx)
971 AUTOCHANGER *changer;
974 Dmsg1(dbglvl, "search res for %s\n", rctx.device_name);
975 /* Look through Autochangers first */
976 foreach_res(changer, R_AUTOCHANGER) {
977 Dmsg1(dbglvl, "Try match changer res=%s\n", changer->hdr.name);
978 /* Find resource, and make sure we were able to open it */
979 if (strcmp(rctx.device_name, changer->hdr.name) == 0) {
980 /* Try each device in this AutoChanger */
981 foreach_alist(rctx.device, changer->device) {
982 Dmsg1(dbglvl, "Try changer device %s\n", rctx.device->hdr.name);
983 stat = reserve_device(rctx);
984 if (stat != 1) { /* try another device */
988 if (rctx.store->append == SD_APPEND) {
989 Dmsg2(dbglvl, "Device %s reserved=%d for append.\n",
990 rctx.device->hdr.name, rctx.jcr->dcr->dev->reserved_device);
992 Dmsg2(dbglvl, "Device %s reserved=%d for read.\n",
993 rctx.device->hdr.name, rctx.jcr->read_dcr->dev->reserved_device);
1000 /* Now if requested look through regular devices */
1001 if (!rctx.autochanger_only) {
1002 foreach_res(rctx.device, R_DEVICE) {
1003 Dmsg1(dbglvl, "Try match res=%s\n", rctx.device->hdr.name);
1004 /* Find resource, and make sure we were able to open it */
1005 if (strcmp(rctx.device_name, rctx.device->hdr.name) == 0) {
1006 stat = reserve_device(rctx);
1007 if (stat != 1) { /* try another device */
1011 if (rctx.store->append == SD_APPEND) {
1012 Dmsg2(dbglvl, "Device %s reserved=%d for append.\n",
1013 rctx.device->hdr.name, rctx.jcr->dcr->dev->reserved_device);
1015 Dmsg2(dbglvl, "Device %s reserved=%d for read.\n",
1016 rctx.device->hdr.name, rctx.jcr->read_dcr->dev->reserved_device);
1022 return -1; /* nothing found */
1026 * Try to reserve a specific device.
1028 * Returns: 1 -- OK, have DCR
1032 static int reserve_device(RCTX &rctx)
1036 const int name_len = MAX_NAME_LENGTH;
1038 /* Make sure MediaType is OK */
1039 Dmsg2(dbglvl, "chk MediaType device=%s request=%s\n",
1040 rctx.device->media_type, rctx.store->media_type);
1041 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
1045 /* Make sure device exists -- i.e. we can stat() it */
1046 if (!rctx.device->dev) {
1047 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
1049 if (!rctx.device->dev) {
1050 if (rctx.device->changer_res) {
1051 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
1052 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
1053 rctx.device->hdr.name, rctx.device_name);
1055 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
1056 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
1059 return -1; /* no use waiting */
1062 rctx.suitable_device = true;
1063 Dmsg1(dbglvl, "try reserve %s\n", rctx.device->hdr.name);
1064 rctx.jcr->dcr = dcr = new_dcr(rctx.jcr, rctx.jcr->dcr, rctx.device->dev);
1066 BSOCK *dir = rctx.jcr->dir_bsock;
1067 dir->fsend(_("3926 Could not get dcr for device: %s\n"), rctx.device_name);
1068 Dmsg1(dbglvl, ">dird: %s", dir->msg);
1071 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
1072 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
1073 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
1074 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
1075 if (rctx.store->append == SD_APPEND) {
1076 Dmsg2(dbglvl, "have_vol=%d vol=%s\n", rctx.have_volume, rctx.VolumeName);
1077 ok = reserve_device_for_append(dcr, rctx);
1082 rctx.jcr->dcr = dcr;
1083 Dmsg5(dbglvl, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
1084 dcr->dev->reserved_device,
1085 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
1086 if (!rctx.have_volume) {
1087 dcr->any_volume = true;
1088 if (dir_find_next_appendable_volume(dcr)) {
1089 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
1090 Dmsg1(dbglvl, "looking for Volume=%s\n", rctx.VolumeName);
1091 rctx.have_volume = true;
1093 Dmsg0(dbglvl, "No next volume found\n");
1094 rctx.have_volume = false;
1095 rctx.VolumeName[0] = 0;
1097 * If there is at least one volume that is valid and in use,
1098 * but we get here, check if we are running with prefers
1099 * non-mounted drives. In that case, we have selected a
1100 * non-used drive and our one and only volume is mounted
1101 * elsewhere, so we bail out and retry using that drive.
1103 if (dcr->volume_in_use && !rctx.PreferMountedVols) {
1104 rctx.PreferMountedVols = true;
1105 if (dcr->VolumeName[0]) {
1111 * Note. Under some circumstances, the Director can hand us
1112 * a Volume name that is no the same as the one on the current
1113 * drive, and in that case, the call above to find the next
1114 * volume will fail because in attempting to reserve the Volume
1115 * the code will realize that we already have a tape mounted,
1116 * and it will fail. This *should* only happen if there are
1117 * writers, thus the following test. In that case, we simply
1118 * bail out, and continue waiting, rather than plunging on
1119 * and hoping that the operator can resolve the problem.
1121 if (dcr->dev->num_writers != 0) {
1122 if (dcr->VolumeName[0]) {
1130 ok = reserve_device_for_read(dcr);
1132 rctx.jcr->read_dcr = dcr;
1133 Dmsg5(dbglvl, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
1134 dcr->dev->reserved_device,
1135 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
1141 if (rctx.notify_dir) {
1143 BSOCK *dir = rctx.jcr->dir_bsock;
1144 pm_strcpy(dev_name, rctx.device->hdr.name);
1145 bash_spaces(dev_name);
1146 ok = dir->fsend(OK_device, dev_name.c_str()); /* Return real device name */
1147 Dmsg1(dbglvl, ">dird: %s", dir->msg);
1154 rctx.have_volume = false;
1156 Dmsg0(dbglvl, "Not OK.\n");
1161 * We "reserve" the drive by setting the ST_READ bit. No one else
1162 * should touch the drive until that is cleared.
1163 * This allows the DIR to "reserve" the device before actually
1166 static bool reserve_device_for_read(DCR *dcr)
1168 DEVICE *dev = dcr->dev;
1169 JCR *jcr = dcr->jcr;
1176 if (is_device_unmounted(dev)) {
1177 Dmsg1(dbglvl, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
1178 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
1179 jcr->JobId, dev->print_name());
1180 queue_reserve_message(jcr);
1184 if (dev->is_busy()) {
1185 Dmsg4(dbglvl, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n",
1187 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
1188 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
1189 jcr->JobId, dev->print_name());
1190 queue_reserve_message(jcr);
1194 dev->clear_append();
1197 dev->reserved_device++;
1198 Dmsg3(dbglvl, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, dev->print_name(), dev);
1199 dcr->reserved_device = true;
1208 * We reserve the device for appending by incrementing the
1209 * reserved_device. We do virtually all the same work that
1210 * is done in acquire_device_for_append(), but we do
1211 * not attempt to mount the device. This routine allows
1212 * the DIR to reserve multiple devices before *really*
1213 * starting the job. It also permits the SD to refuse
1214 * certain devices (not up, ...).
1216 * Note, in reserving a device, if the device is for the
1217 * same pool and the same pool type, then it is acceptable.
1218 * The Media Type has already been checked. If we are
1219 * the first tor reserve the device, we put the pool
1220 * name and pool type in the device record.
1222 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
1224 JCR *jcr = dcr->jcr;
1225 DEVICE *dev = dcr->dev;
1232 /* If device is being read, we cannot write it */
1233 if (dev->can_read()) {
1234 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
1235 jcr->JobId, dev->print_name());
1236 Dmsg1(dbglvl, "%s", jcr->errmsg);
1237 queue_reserve_message(jcr);
1241 /* If device is unmounted, we are out of luck */
1242 if (is_device_unmounted(dev)) {
1243 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
1244 jcr->JobId, dev->print_name());
1245 Dmsg1(dbglvl, "%s", jcr->errmsg);
1246 queue_reserve_message(jcr);
1250 Dmsg1(dbglvl, "reserve_append device is %s\n", dev->print_name());
1252 /* Now do detailed tests ... */
1253 if (can_reserve_drive(dcr, rctx) != 1) {
1254 Dmsg0(dbglvl, "can_reserve_drive!=1\n");
1258 dev->reserved_device++;
1259 Dmsg3(dbglvl, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
1260 dev->print_name(), dev);
1261 dcr->reserved_device = true;
1269 static int is_pool_ok(DCR *dcr)
1271 DEVICE *dev = dcr->dev;
1272 JCR *jcr = dcr->jcr;
1274 /* Now check if we want the same Pool and pool type */
1275 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1276 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1277 /* OK, compatible device */
1278 Dmsg1(dbglvl, "OK dev: %s num_writers=0, reserved, pool matches\n", dev->print_name());
1281 /* Drive Pool not suitable for us */
1282 Mmsg(jcr->errmsg, _(
1283 "3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"),
1284 (uint32_t)jcr->JobId, dcr->pool_name, dev->pool_name,
1285 dev->reserved_device, dev->print_name());
1286 queue_reserve_message(jcr);
1287 Dmsg2(dbglvl, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
1288 dev->pool_name, dcr->pool_name);
1293 static bool is_max_jobs_ok(DCR *dcr)
1295 DEVICE *dev = dcr->dev;
1296 JCR *jcr = dcr->jcr;
1298 Dmsg4(dbglvl, "MaxJobs=%d Jobs=%d reserves=%d Vol=%s\n",
1299 dcr->VolCatInfo.VolCatMaxJobs,
1300 dcr->VolCatInfo.VolCatJobs, dev->reserved_device,
1302 if (dcr->VolCatInfo.VolCatMaxJobs > 0 && dcr->VolCatInfo.VolCatMaxJobs <=
1303 (dcr->VolCatInfo.VolCatJobs + dev->reserved_device)) {
1304 /* Max Job Vols depassed or already reserved */
1305 Mmsg(jcr->errmsg, _("3610 JobId=%u Volume max jobs exceeded on drive %s.\n"),
1306 (uint32_t)jcr->JobId, dev->print_name());
1307 queue_reserve_message(jcr);
1308 Dmsg1(dbglvl, "reserve dev failed: %s", jcr->errmsg);
1309 return false; /* wait */
1315 * Returns: 1 if drive can be reserved
1316 * 0 if we should wait
1317 * -1 on error or impossibility
1319 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
1321 DEVICE *dev = dcr->dev;
1322 JCR *jcr = dcr->jcr;
1324 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
1325 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1326 rctx.autochanger_only, rctx.any_drive);
1328 /* Check for max jobs on this Volume */
1329 if (!is_max_jobs_ok(dcr)) {
1333 /* setting any_drive overrides PreferMountedVols flag */
1334 if (!rctx.any_drive) {
1336 * When PreferMountedVols is set, we keep track of the
1337 * drive in use that has the least number of writers, then if
1338 * no unmounted drive is found, we try that drive. This
1339 * helps spread the load to the least used drives.
1341 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
1342 Dmsg2(dbglvl, "OK dev=%s == low_drive=%s.\n",
1343 dev->print_name(), rctx.low_use_drive->print_name());
1346 /* If he wants a free drive, but this one is busy, no go */
1347 if (!rctx.PreferMountedVols && dev->is_busy()) {
1348 /* Save least used drive */
1349 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
1350 rctx.num_writers = dev->num_writers + dev->reserved_device;
1351 rctx.low_use_drive = dev;
1352 Dmsg2(dbglvl, "set low use drive=%s num_writers=%d\n",
1353 dev->print_name(), rctx.num_writers);
1355 Dmsg1(dbglvl, "not low use num_writers=%d\n", dev->num_writers+dev->reserved_device);
1357 Dmsg0(dbglvl, "failed: !prefMnt && busy.\n");
1358 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
1359 jcr->JobId, dev->print_name());
1360 queue_reserve_message(jcr);
1364 /* Check for prefer mounted volumes */
1365 if (rctx.PreferMountedVols && !dev->vol && dev->is_tape()) {
1366 Mmsg(jcr->errmsg, _("3606 JobId=%u prefers mounted drives, but drive %s has no Volume.\n"),
1367 jcr->JobId, dev->print_name());
1368 queue_reserve_message(jcr);
1369 Dmsg0(dbglvl, "failed: want mounted -- no vol\n");
1370 return 0; /* No volume mounted */
1373 /* Check for exact Volume name match */
1374 /* ***FIXME*** for Disk, we can accept any volume that goes with this
1377 if (rctx.exact_match && rctx.have_volume) {
1379 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
1380 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1381 rctx.autochanger_only, rctx.any_drive);
1382 Dmsg4(dbglvl, "have_vol=%d have=%s resvol=%s want=%s\n",
1383 rctx.have_volume, dev->VolHdr.VolumeName,
1384 dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName);
1385 ok = strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) == 0 ||
1386 (dev->vol && strcmp(dev->vol->vol_name, rctx.VolumeName) == 0);
1388 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
1389 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
1391 queue_reserve_message(jcr);
1392 Dmsg3(dbglvl, "not OK: dev have=%s resvol=%s want=%s\n",
1393 dev->VolHdr.VolumeName, dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName);
1396 if (is_volume_in_use(dcr)) {
1397 return 0; /* fail if volume on another drive */
1402 /* Check for unused autochanger drive */
1403 if (rctx.autochanger_only && !dev->is_busy() &&
1404 dev->VolHdr.VolumeName[0] == 0) {
1405 /* Device is available but not yet reserved, reserve it for us */
1406 Dmsg1(dbglvl, "OK Res Unused autochanger %s.\n", dev->print_name());
1407 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1408 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1409 return 1; /* reserve drive */
1413 * Handle the case that there are no writers
1415 if (dev->num_writers == 0) {
1416 /* Now check if there are any reservations on the drive */
1417 if (dev->reserved_device) {
1418 return is_pool_ok(dcr);
1419 } else if (dev->can_append()) {
1420 if (is_pool_ok(dcr)) {
1423 /* Changing pool, unload old tape if any in drive */
1424 Dmsg0(dbglvl, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
1425 unload_autochanger(dcr, 0);
1428 /* Device is available but not yet reserved, reserve it for us */
1429 Dmsg1(dbglvl, "OK Dev avail reserved %s\n", dev->print_name());
1430 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1431 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1432 return 1; /* reserve drive */
1436 * Check if the device is in append mode with writers (i.e.
1437 * available if pool is the same).
1439 if (dev->can_append() || dev->num_writers > 0) {
1440 return is_pool_ok(dcr);
1442 Pmsg1(000, _("Logic error!!!! JobId=%u Should not get here.\n"), (int)jcr->JobId);
1443 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
1444 jcr->JobId, dev->print_name());
1445 queue_reserve_message(jcr);
1446 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
1447 return -1; /* error, should not get here */
1449 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
1450 jcr->JobId, dev->print_name());
1451 queue_reserve_message(jcr);
1452 Dmsg1(dbglvl, "failed: No reserve %s\n", dev->print_name());
1460 * Queue a reservation error or failure message for this jcr
1462 static void queue_reserve_message(JCR *jcr)
1470 msgs = jcr->reserve_msgs;
1475 * Look for duplicate message. If found, do
1478 for (i=msgs->size()-1; i >= 0; i--) {
1479 msg = (char *)msgs->get(i);
1483 /* Comparison based on 4 digit message number */
1484 if (strncmp(msg, jcr->errmsg, 4) == 0) {
1488 /* Message unique, so insert it */
1489 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1496 * Send any reservation messages queued for this jcr
1498 void send_drive_reserve_messages(JCR *jcr, void sendit(const char *msg, int len, void *sarg), void *arg)
1505 msgs = jcr->reserve_msgs;
1506 if (!msgs || msgs->size() == 0) {
1509 for (i=msgs->size()-1; i >= 0; i--) {
1510 msg = (char *)msgs->get(i);
1512 sendit(" ", 3, arg);
1513 sendit(msg, strlen(msg), arg);
1524 * Pop and release any reservations messages
1526 static void pop_reserve_messages(JCR *jcr)
1532 msgs = jcr->reserve_msgs;
1536 while ((msg = (char *)msgs->pop())) {
1544 * Also called from acquire.c
1546 void release_reserve_messages(JCR *jcr)
1548 pop_reserve_messages(jcr);
1550 if (!jcr->reserve_msgs) {
1553 delete jcr->reserve_msgs;
1554 jcr->reserve_msgs = NULL;