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 plus additions
11 that are listed in the file LICENSE.
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);
56 /* Requests from the Director daemon */
57 static char use_storage[] = "use storage=%127s media_type=%127s "
58 "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
59 static char use_device[] = "use device=%127s\n";
61 /* Responses sent to Director daemon */
62 static char OK_device[] = "3000 OK use device device=%s\n";
63 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
64 static char BAD_use[] = "3913 Bad use command: %s\n";
66 bool use_cmd(JCR *jcr)
69 * Get the device, media, and pool information
71 if (!use_storage_cmd(jcr)) {
72 set_jcr_job_status(jcr, JS_ErrorTerminated);
73 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
79 static int my_compare(void *item1, void *item2)
81 return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
85 void init_reservations_lock()
88 if ((errstat=rwl_init(&reservation_lock)) != 0) {
90 Emsg1(M_ABORT, 0, _("Unable to initialize reservation lock. ERR=%s\n"),
91 be.bstrerror(errstat));
94 if ((errstat=rwl_init(&vol_list_lock)) != 0) {
96 Emsg1(M_ABORT, 0, _("Unable to initialize volume list lock. ERR=%s\n"),
97 be.bstrerror(errstat));
101 void term_reservations_lock()
103 rwl_destroy(&reservation_lock);
104 rwl_destroy(&vol_list_lock);
107 int reservations_lock_count = 0;
109 /* This applies to a drive and to Volumes */
110 void _lock_reservations()
113 reservations_lock_count++;
114 if ((errstat=rwl_writelock(&reservation_lock)) != 0) {
116 Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
117 errstat, be.bstrerror(errstat));
121 void _unlock_reservations()
124 reservations_lock_count--;
125 if ((errstat=rwl_writeunlock(&reservation_lock)) != 0) {
127 Emsg2(M_ABORT, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
128 errstat, be.bstrerror(errstat));
132 int vol_list_lock_count = 0;
137 vol_list_lock_count++;
138 if ((errstat=rwl_writelock(&vol_list_lock)) != 0) {
140 Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
141 errstat, be.bstrerror(errstat));
145 void _unlock_volumes()
148 vol_list_lock_count--;
149 if ((errstat=rwl_writeunlock(&vol_list_lock)) != 0) {
151 Emsg2(M_ABORT, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
152 errstat, be.bstrerror(errstat));
158 * List Volumes -- this should be moved to status.c
165 static void debug_list_volumes(const char *imsg)
168 POOL_MEM msg(PM_MESSAGE);
171 foreach_dlist(vol, vol_list) {
173 Mmsg(msg, "List from %s: %s at %p on device %s\n", imsg,
174 vol->vol_name, vol->vol_name, vol->dev->print_name());
176 Mmsg(msg, "List from %s: %s at %p no dev\n", imsg, vol->vol_name, vol->vol_name);
178 Dmsg1(dbglvl, "%s", msg.c_str());
183 foreach_dlist(vol, vol_list) {
184 if (vol->dev == dev) {
185 Dmsg0(000, "Two Volumes on same device.\n");
192 // Dmsg2(dbglvl, "List from %s: %d volumes\n", imsg, count);
198 * List Volumes -- this should be moved to status.c
200 void list_volumes(void sendit(const char *msg, int len, void *sarg), void *arg)
203 POOL_MEM msg(PM_MESSAGE);
207 foreach_dlist(vol, vol_list) {
209 len = Mmsg(msg, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
210 sendit(msg.c_str(), len, arg);
212 len = Mmsg(msg, "%s no dev\n", vol->vol_name);
213 sendit(msg.c_str(), len, arg);
220 * Create a Volume item to put in the Volume list
221 * Ensure that the device points to it.
223 static VOLRES *new_vol_item(DCR *dcr, const char *VolumeName)
226 vol = (VOLRES *)malloc(sizeof(VOLRES));
227 memset(vol, 0, sizeof(VOLRES));
228 vol->vol_name = bstrdup(VolumeName);
230 Dmsg4(dbglvl, "JobId=%u new Vol=%s at %p dev=%s\n", (int)dcr->jcr->JobId,
231 VolumeName, vol->vol_name, vol->dev->print_name());
235 static void free_vol_item(VOLRES *vol)
239 vol->dev->vol = NULL;
246 * Put a new Volume entry in the Volume list. This
247 * effectively reserves the volume so that it will
248 * not be mounted again.
250 * If the device has any current volume associated with it,
251 * and it is a different Volume, and the device is not busy,
252 * we release the old Volume item and insert the new one.
254 * It is assumed that the device is free and locked so that
255 * we can change the device structure.
257 * Some details of the Volume list handling:
259 * 1. The Volume list entry must be attached to the drive (rather than
260 * attached to a job as it currently is. I.e. the drive that "owns"
261 * the volume (reserved, in use, mounted)
262 * must point to the volume (still to be maintained in a list).
264 * 2. The Volume is entered in the list when a drive is reserved.
266 * 3. When a drive is in use, the device code must appropriately update the
267 * volume name as it changes (currently the list is static -- an entry is
268 * removed when the Volume is no longer reserved, in use or mounted).
269 * The new code must keep the same list entry as long as the drive
270 * has any volume associated with it but the volume name in the list
271 * must be updated when the drive has a different volume mounted.
273 * 4. A job that has reserved a volume, can un-reserve the volume, and if the
274 * volume is not mounted, and not reserved, and not in use, it will be
275 * removed from the list.
277 * 5. If a job wants to reserve a drive with a different Volume from the one on
278 * the drive, it can re-use the drive for the new Volume.
280 * 6. If a job wants a Volume that is in a different drive, it can either use the
281 * other drive or take the volume, only if the other drive is not in use or
284 * One nice aspect of this is that the reserve use count and the writer use count
285 * already exist and are correctly programmed and will need no changes -- use
286 * counts are always very tricky.
288 * The old code had a concept of "reserving" a Volume, but it needs to be changed
289 * to reserving and using a drive. A volume is must be attached to (owned by) a
290 * drive and can move from drive to drive or be unused given certain specific
291 * conditions of the drive. The key is that the drive must "own" the Volume.
292 * The old code has the job (dcr) owning the volume (more or less). The job is
293 * to change the insertion and removal of the volumes from the list to be based
294 * on the drive rather than the job.
296 * Return: VOLRES entry on success
297 * NULL volume busy on another drive
299 VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
302 DEVICE *dev = dcr->dev;
306 Dmsg1(dbglvl, "reserve_volume %s\n", VolumeName);
308 * We lock the reservations system here to ensure
309 * when adding a new volume that no newly scheduled
310 * job can reserve it.
313 debug_list_volumes("begin reserve_volume");
315 * First, remove any old volume attached to this device as it
321 * Make sure we don't remove the current volume we are inserting
322 * because it was probably inserted by another job.
324 if (strcmp(vol->vol_name, VolumeName) == 0) {
325 goto get_out; /* Volume already on this device */
327 Dmsg3(dbglvl, "reserve_vol free vol=%s at %p JobId=%u\n", vol->vol_name,
328 vol->vol_name, (int)dcr->jcr->JobId);
329 debug_list_volumes("reserve_vol free");
330 vol_list->remove(vol);
335 /* Create a new Volume entry */
336 nvol = new_vol_item(dcr, VolumeName);
339 * Now try to insert the new Volume
341 vol = (VOLRES *)vol_list->binary_insert(nvol, my_compare);
343 Dmsg2(dbglvl, "Found vol=%s dev-same=%d\n", vol->vol_name, dev==vol->dev);
345 * At this point, a Volume with this name already is in the list,
346 * so we simply release our new Volume entry. Note, this should
347 * only happen if we are moving the volume from one drive to another.
349 Dmsg3(dbglvl, "reserve_vol free-tmp vol=%s at %p JobId=%u\n", vol->vol_name,
350 vol->vol_name, (int)dcr->jcr->JobId);
352 * Clear dev pointer so that free_vol_item() doesn't
353 * take away our volume.
355 nvol->dev = NULL; /* don't zap dev entry */
358 /* Check if we are trying to use the Volume on a different drive */
359 if (dev != vol->dev) {
360 /* Caller wants to switch Volume to another device */
361 if (!vol->dev->is_busy()) {
362 /* OK to move it -- I'm not sure this will work */
363 Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n", VolumeName,
364 vol->dev->print_name(), dev->print_name());
365 vol->dev->vol = NULL; /* take vol from old drive */
366 vol->dev->VolHdr.VolumeName[0] = 0;
367 vol->dev = dev; /* point vol at new drive */
368 dev->vol = vol; /* point dev at vol */
369 dev->VolHdr.VolumeName[0] = 0;
371 Dmsg3(dbglvl, "Volume busy could not swap vol=%s from dev=%s to %s\n", VolumeName,
372 vol->dev->print_name(), dev->print_name());
373 vol = NULL; /* device busy */
380 debug_list_volumes("end new volume");
386 * Search for a Volume name in the Volume list.
388 * Returns: VOLRES entry on success
389 * NULL if the Volume is not in the list
391 VOLRES *find_volume(DCR *dcr)
394 /* Do not lock reservations here */
396 vol.vol_name = bstrdup(dcr->VolumeName);
397 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
399 Dmsg2(dbglvl, "find_vol=%s found=%d\n", dcr->VolumeName, fvol!=NULL);
400 debug_list_volumes("find_volume");
406 * Remove any reservation from a drive and tell the system
407 * that the volume is unused at least by us.
409 void unreserve_device(DCR *dcr)
411 DEVICE *dev = dcr->dev;
413 if (dcr->reserved_device) {
414 dcr->reserved_device = false;
415 dev->reserved_device--;
416 Dmsg2(dbglvl, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
417 dcr->reserved_device = false;
418 /* If we set read mode in reserving, remove it */
419 if (dev->can_read()) {
422 if (dev->num_writers < 0) {
423 Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
424 dev->num_writers = 0;
433 * Free a Volume from the Volume list if it is no longer used
435 * Returns: true if the Volume found and removed from the list
436 * false if the Volume is not in the list or is in use
438 bool volume_unused(DCR *dcr)
440 DEVICE *dev = dcr->dev;
442 if (dev->vol == NULL) {
443 Dmsg2(dbglvl, "JobId=%u vol_unused: no vol on %s\n", (int)dcr->jcr->JobId, dev->print_name());
444 debug_list_volumes("null return unreserve_volume");
448 if (dev->is_busy()) {
449 Dmsg2(dbglvl, "JobId=%u vol_unused: no vol on %s\n", (int)dcr->jcr->JobId, dev->print_name());
450 debug_list_volumes("dev busy return unreserve_volume");
454 return free_volume(dev);
458 * Unconditionally release the volume
460 bool free_volume(DEVICE *dev)
464 if (dev->vol == NULL) {
465 Dmsg1(dbglvl, "No vol on dev %s\n", dev->print_name());
471 vol_list->remove(vol);
472 Dmsg2(dbglvl, "free_volume %s dev=%s\n", vol->vol_name, dev->print_name());
474 debug_list_volumes("free_volume");
480 /* Create the Volume list */
481 void create_volume_list()
484 if (vol_list == NULL) {
485 vol_list = New(dlist(vol, &vol->link));
489 /* Release all Volumes from the list */
490 void free_volume_list()
497 foreach_dlist(vol, vol_list) {
498 Dmsg2(dbglvl, "Unreleased Volume=%s dev=%p\n", vol->vol_name, vol->dev);
500 vol->vol_name = NULL;
507 bool is_volume_in_use(DCR *dcr)
509 VOLRES *vol = find_volume(dcr);
511 Dmsg1(dbglvl, "Vol=%s not in use.\n", dcr->VolumeName);
512 return false; /* vol not in list */
514 ASSERT(vol->dev != NULL);
516 if (dcr->dev == vol->dev) { /* same device OK */
517 Dmsg1(dbglvl, "Vol=%s on same dev.\n", dcr->VolumeName);
520 Dmsg3(dbglvl, "Vol=%s on %s we have %s\n", dcr->VolumeName,
521 vol->dev->print_name(), dcr->dev->print_name());
523 if (!vol->dev->is_busy()) {
524 Dmsg2(dbglvl, "Vol=%s dev=%s not busy.\n", dcr->VolumeName, vol->dev->print_name());
527 Dmsg2(dbglvl, "Vol=%s dev=%s busy.\n", dcr->VolumeName, vol->dev->print_name());
529 Dmsg2(dbglvl, "Vol=%s in use by %s.\n", dcr->VolumeName, vol->dev->print_name());
535 * We get the following type of information:
537 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
541 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
545 static bool use_storage_cmd(JCR *jcr)
547 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
548 BSOCK *dir = jcr->dir_bsock;
558 memset(&rctx, 0, sizeof(RCTX));
561 * If there are multiple devices, the director sends us
562 * use_device for each device that it wants to use.
564 dirstore = New(alist(10, not_owned_by_alist));
565 msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
567 Dmsg1(dbglvl, "<dird: %s", dir->msg);
568 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
569 media_type.c_str(), pool_name.c_str(),
570 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
575 jcr->write_store = dirstore;
577 jcr->read_store = dirstore;
579 rctx.append = append;
580 unbash_spaces(store_name);
581 unbash_spaces(media_type);
582 unbash_spaces(pool_name);
583 unbash_spaces(pool_type);
584 store = new DIRSTORE;
585 dirstore->append(store);
586 memset(store, 0, sizeof(DIRSTORE));
587 store->device = New(alist(10));
588 bstrncpy(store->name, store_name, sizeof(store->name));
589 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
590 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
591 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
592 store->append = append;
594 /* Now get all devices */
595 while (dir->recv() >= 0) {
596 Dmsg1(dbglvl, "<dird device: %s", dir->msg);
597 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
601 unbash_spaces(dev_name);
602 store->device->append(bstrdup(dev_name.c_str()));
604 } while (ok && dir->recv() >= 0);
606 /* Developer debug code */
608 if (debug_level >= dbglvl) {
609 foreach_alist(store, dirstore) {
610 Dmsg6(dbglvl, "JobId=%u Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n",
611 (int)rctx.jcr->JobId,
612 store->name, store->media_type, store->pool_name,
613 store->pool_type, store->append);
614 foreach_alist(device_name, store->device) {
615 Dmsg1(dbglvl, " Device=%s\n", device_name);
620 init_jcr_device_wait_timers(jcr);
622 * At this point, we have a list of all the Director's Storage
623 * resources indicated for this Job, which include Pool, PoolType,
624 * storage name, and Media type.
625 * Then for each of the Storage resources, we have a list of
626 * device names that were given.
628 * Wiffle through them and find one that can do the backup.
631 int wait_for_device_retries = 0;
634 rctx.notify_dir = true;
636 for ( ; !fail && !job_canceled(jcr); ) {
637 while ((msg = (char *)msgs->pop())) {
640 rctx.suitable_device = false;
641 rctx.have_volume = false;
642 rctx.VolumeName[0] = 0;
643 rctx.any_drive = false;
644 if (!jcr->PreferMountedVols) {
645 /* Look for unused drives in autochangers */
646 rctx.num_writers = 20000000; /* start with impossible number */
647 rctx.low_use_drive = NULL;
648 rctx.PreferMountedVols = false;
649 rctx.exact_match = false;
650 rctx.autochanger_only = true;
651 Dmsg6(dbglvl, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
652 (int)rctx.jcr->JobId,
653 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
654 rctx.autochanger_only, rctx.any_drive);
655 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
658 /* Look through all drives possibly for low_use drive */
659 if (rctx.low_use_drive) {
660 rctx.try_low_use_drive = true;
661 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
664 rctx.try_low_use_drive = false;
666 rctx.autochanger_only = false;
667 Dmsg6(dbglvl, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
668 (int)rctx.jcr->JobId,
669 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
670 rctx.autochanger_only, rctx.any_drive);
671 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
675 /* Look for an exact match all drives */
676 rctx.PreferMountedVols = true;
677 rctx.exact_match = true;
678 rctx.autochanger_only = false;
679 Dmsg6(dbglvl, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
680 (int)rctx.jcr->JobId,
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 for any mounted drive */
687 rctx.exact_match = false;
688 Dmsg6(dbglvl, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
689 (int)rctx.jcr->JobId,
690 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
691 rctx.autochanger_only, rctx.any_drive);
692 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
696 rctx.any_drive = true;
697 Dmsg6(dbglvl, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
698 (int)rctx.jcr->JobId,
699 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
700 rctx.autochanger_only, rctx.any_drive);
701 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
704 /* Keep reservations locked *except* during wait_for_device() */
705 unlock_reservations();
707 * The idea of looping on repeat a few times it to ensure
708 * that if there is some subtle timing problem between two
709 * jobs, we will simply try again, and most likely succeed.
710 * This can happen if one job reserves a drive or finishes using
711 * a drive at the same time a second job wants it.
713 if (repeat++ > 1) { /* try algorithm 3 times */
714 bmicrosleep(30, 0); /* wait a bit */
715 Dmsg1(dbglvl, "JobId=%u repeat reserve algorithm\n", (int)rctx.jcr->JobId);
716 } else if (!rctx.suitable_device || !wait_for_device(jcr, wait_for_device_retries)) {
717 Dmsg1(dbglvl, "JobId=%u Fail. !suitable_device || !wait_for_device\n",
718 (int)rctx.jcr->JobId);
722 dir->signal(BNET_HEARTBEAT); /* Inform Dir that we are alive */
724 unlock_reservations();
727 * If we get here, there are no suitable devices available, which
728 * means nothing configured. If a device is suitable but busy
729 * with another Volume, we will not come here.
731 unbash_spaces(dir->msg);
732 pm_strcpy(jcr->errmsg, dir->msg);
733 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
734 Jmsg(jcr, M_FATAL, 0, _("\n"
735 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
736 dev_name.c_str(), media_type.c_str());
737 dir->fsend(NO_device, dev_name.c_str());
739 Dmsg1(dbglvl, ">dird: %s", dir->msg);
742 unbash_spaces(dir->msg);
743 pm_strcpy(jcr->errmsg, dir->msg);
744 Jmsg(jcr, M_FATAL, 0, _("Failed command: %s\n"), jcr->errmsg);
745 dir->fsend(BAD_use, jcr->errmsg);
746 Dmsg1(dbglvl, ">dird: %s", dir->msg);
753 void release_msgs(JCR *jcr)
755 alist *msgs = jcr->reserve_msgs;
762 while ((msg = (char *)msgs->pop())) {
766 jcr->reserve_msgs = NULL;
767 unlock_reservations();
771 * Search for a device suitable for this job.
773 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
781 dirstore = jcr->write_store;
783 dirstore = jcr->read_store;
785 Dmsg5(dbglvl, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
786 (int)rctx.jcr->JobId,
787 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
788 rctx.autochanger_only);
790 if (!vol_list->empty() && rctx.append && rctx.PreferMountedVols) {
791 dlist *temp_vol_list, *save_vol_list;
796 * Create a temporary copy of the volume list. We do this,
797 * to avoid having the volume list locked during the
798 * call to reserve_device(), which would cause a deadlock.
799 * Note, we may want to add an update counter on the vol_list
800 * so that if it is modified while we are traversing the copy
801 * we can take note and act accordingly (probably redo the
802 * search at least a few times).
804 temp_vol_list = New(dlist(vol, &vol->link));
805 foreach_dlist(vol, vol_list) {
807 VOLRES *tvol = (VOLRES *)malloc(sizeof(VOLRES));
808 memset(tvol, 0, sizeof(VOLRES));
809 tvol->vol_name = bstrdup(vol->vol_name);
810 tvol->dev = vol->dev;
811 nvol = (VOLRES *)temp_vol_list->binary_insert(tvol, my_compare);
813 tvol->dev = NULL; /* don't zap dev entry */
815 Pmsg0(000, "Logic error. Duplicating vol list hit duplicate.\n");
816 Jmsg(jcr, M_WARNING, 0, "Logic error. Duplicating vol list hit duplicate.\n");
821 /* Look through reserved volumes for one we can use */
822 foreach_dlist(vol, temp_vol_list) {
826 foreach_alist(store, dirstore) {
828 foreach_alist(device_name, store->device) {
830 if (strcmp(device_name, vol->dev->device->hdr.name) != 0) {
833 rctx.device_name = device_name;
834 rctx.device = vol->dev->device;
835 bstrncpy(rctx.VolumeName, vol->vol_name, sizeof(rctx.VolumeName));
836 rctx.have_volume = true;
837 /* Try reserving this device and volume */
838 Dmsg3(dbglvl, "JobId=%u try vol=%s on device=%s\n", (int)rctx.jcr->JobId,
839 rctx.VolumeName, device_name);
840 stat = reserve_device(rctx);
841 if (stat == 1) { /* found available device */
842 Dmsg2(dbglvl, "JobId=%u Suitable device found=%s\n", (int)rctx.jcr->JobId,
846 } else if (stat == 0) { /* device busy */
847 Dmsg2(dbglvl, "JobId=%u Suitable device=%s, busy: not use\n",
848 (int)rctx.jcr->JobId, device_name);
850 /* otherwise error */
851 Dmsg1(dbglvl, "JobId=%u No suitable device found.\n", (int)rctx.jcr->JobId);
853 rctx.have_volume = false;
859 } /* end for loop over reserved volumes */
861 save_vol_list = vol_list;
862 vol_list = temp_vol_list;
863 free_volume_list(); /* release temp_vol_list */
864 vol_list = save_vol_list;
872 * No reserved volume we can use, so now search for an available device.
874 * For each storage device that the user specified, we
875 * search and see if there is a resource for that device.
877 foreach_alist(store, dirstore) {
879 foreach_alist(device_name, store->device) {
881 rctx.device_name = device_name;
882 stat = search_res_for_device(rctx);
883 if (stat == 1) { /* found available device */
884 Dmsg2(dbglvl, "JobId=%u Suitable device found=%s\n", (int)rctx.jcr->JobId,
888 } else if (stat == 0) { /* device busy */
889 Dmsg2(dbglvl, "JobId=%u Suitable device=%s, busy: not use\n",
890 (int)rctx.jcr->JobId, device_name);
892 /* otherwise error */
893 Dmsg1(dbglvl, "JobId=%u No suitable device found.\n", (int)rctx.jcr->JobId);
904 * Search for a particular storage device with particular storage
905 * characteristics (MediaType).
907 int search_res_for_device(RCTX &rctx)
909 AUTOCHANGER *changer;
912 Dmsg2(dbglvl, "JobId=%u search res for %s\n", (int)rctx.jcr->JobId, rctx.device_name);
913 /* Look through Autochangers first */
914 foreach_res(changer, R_AUTOCHANGER) {
915 Dmsg2(150, "JobId=%u Try match changer res=%s\n", (int)rctx.jcr->JobId, changer->hdr.name);
916 /* Find resource, and make sure we were able to open it */
917 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
918 /* Try each device in this AutoChanger */
919 foreach_alist(rctx.device, changer->device) {
920 Dmsg2(dbglvl, "JobId=%u Try changer device %s\n", (int)rctx.jcr->JobId,
921 rctx.device->hdr.name);
922 stat = reserve_device(rctx);
923 if (stat != 1) { /* try another device */
927 if (rctx.store->append == SD_APPEND) {
928 Dmsg3(dbglvl, "JobId=%u Device %s reserved=%d for append.\n",
929 (int)rctx.jcr->JobId, rctx.device->hdr.name,
930 rctx.jcr->dcr->dev->reserved_device);
932 Dmsg3(dbglvl, "JobId=%u Device %s reserved=%d for read.\n",
933 (int)rctx.jcr->JobId, rctx.device->hdr.name,
934 rctx.jcr->read_dcr->dev->reserved_device);
941 /* Now if requested look through regular devices */
942 if (!rctx.autochanger_only) {
943 foreach_res(rctx.device, R_DEVICE) {
944 Dmsg2(150, "JobId=%u Try match res=%s\n", (int)rctx.jcr->JobId, rctx.device->hdr.name);
945 /* Find resource, and make sure we were able to open it */
946 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
947 stat = reserve_device(rctx);
948 if (stat != 1) { /* try another device */
952 if (rctx.store->append == SD_APPEND) {
953 Dmsg3(dbglvl, "JobId=%u Device %s reserved=%d for append.\n",
954 (int)rctx.jcr->JobId, rctx.device->hdr.name,
955 rctx.jcr->dcr->dev->reserved_device);
957 Dmsg3(dbglvl, "JobId=%u Device %s reserved=%d for read.\n",
958 (int)rctx.jcr->JobId, rctx.device->hdr.name,
959 rctx.jcr->read_dcr->dev->reserved_device);
965 return -1; /* nothing found */
969 * Try to reserve a specific device.
971 * Returns: 1 -- OK, have DCR
975 static int reserve_device(RCTX &rctx)
979 const int name_len = MAX_NAME_LENGTH;
981 /* Make sure MediaType is OK */
982 Dmsg3(dbglvl, "JobId=%u MediaType device=%s request=%s\n",
983 (int)rctx.jcr->JobId,
984 rctx.device->media_type, rctx.store->media_type);
985 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
989 /* Make sure device exists -- i.e. we can stat() it */
990 if (!rctx.device->dev) {
991 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
993 if (!rctx.device->dev) {
994 if (rctx.device->changer_res) {
995 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
996 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
997 rctx.device->hdr.name, rctx.device_name);
999 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
1000 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
1003 return -1; /* no use waiting */
1006 rctx.suitable_device = true;
1007 Dmsg2(dbglvl, "JobId=%u try reserve %s\n", rctx.jcr->JobId, rctx.device->hdr.name);
1008 dcr = new_dcr(rctx.jcr, rctx.device->dev);
1010 BSOCK *dir = rctx.jcr->dir_bsock;
1011 dir->fsend(_("3926 Could not get dcr for device: %s\n"), rctx.device_name);
1012 Dmsg1(dbglvl, ">dird: %s", dir->msg);
1015 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
1016 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
1017 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
1018 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
1019 if (rctx.store->append == SD_APPEND) {
1020 Dmsg3(dbglvl, "JobId=%u have_vol=%d vol=%s\n", (int)rctx.jcr->JobId,
1021 rctx.have_volume, rctx.VolumeName);
1022 if (!rctx.have_volume) {
1023 dcr->any_volume = true;
1024 if (dir_find_next_appendable_volume(dcr)) {
1025 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
1026 Dmsg2(dbglvl, "JobId=%u looking for Volume=%s\n", (int)rctx.jcr->JobId, rctx.VolumeName);
1027 rctx.have_volume = true;
1029 Dmsg1(dbglvl, "JobId=%u No next volume found\n", (int)rctx.jcr->JobId);
1030 rctx.have_volume = false;
1031 rctx.VolumeName[0] = 0;
1034 ok = reserve_device_for_append(dcr, rctx);
1036 rctx.jcr->dcr = dcr;
1037 Dmsg6(dbglvl, "JobId=%u Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
1038 (int)rctx.jcr->JobId,
1039 dcr->dev->reserved_device,
1040 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
1043 ok = reserve_device_for_read(dcr);
1045 rctx.jcr->read_dcr = dcr;
1046 Dmsg6(dbglvl, "JobId=%u Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
1047 (int)rctx.jcr->JobId,
1048 dcr->dev->reserved_device,
1049 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
1053 rctx.have_volume = false;
1055 Dmsg1(dbglvl, "JobId=%u Not OK.\n", (int)rctx.jcr->JobId);
1059 if (rctx.notify_dir) {
1060 BSOCK *dir = rctx.jcr->dir_bsock;
1061 pm_strcpy(dev_name, rctx.device->hdr.name);
1062 bash_spaces(dev_name);
1063 ok = dir->fsend(OK_device, dev_name.c_str()); /* Return real device name */
1064 Dmsg1(dbglvl, ">dird changer: %s", dir->msg);
1072 * We "reserve" the drive by setting the ST_READ bit. No one else
1073 * should touch the drive until that is cleared.
1074 * This allows the DIR to "reserve" the device before actually
1077 static bool reserve_device_for_read(DCR *dcr)
1079 DEVICE *dev = dcr->dev;
1080 JCR *jcr = dcr->jcr;
1087 if (is_device_unmounted(dev)) {
1088 Dmsg2(dbglvl, "JobId=%u Device %s is BLOCKED due to user unmount.\n",
1089 (int)jcr->JobId, dev->print_name());
1090 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
1091 jcr->JobId, dev->print_name());
1092 queue_reserve_message(jcr);
1096 if (dev->is_busy()) {
1097 Dmsg5(dbglvl, "JobId=%u Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n",
1098 (int)jcr->JobId, dev->print_name(),
1099 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
1100 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
1101 jcr->JobId, dev->print_name());
1102 queue_reserve_message(jcr);
1106 dev->clear_append();
1109 dev->reserved_device++;
1110 Dmsg4(dbglvl, "JobId=%u Inc reserve=%d dev=%s %p\n", (int)jcr->JobId,
1111 dev->reserved_device, dev->print_name(), dev);
1112 dcr->reserved_device = true;
1121 * We reserve the device for appending by incrementing the
1122 * reserved_device. We do virtually all the same work that
1123 * is done in acquire_device_for_append(), but we do
1124 * not attempt to mount the device. This routine allows
1125 * the DIR to reserve multiple devices before *really*
1126 * starting the job. It also permits the SD to refuse
1127 * certain devices (not up, ...).
1129 * Note, in reserving a device, if the device is for the
1130 * same pool and the same pool type, then it is acceptable.
1131 * The Media Type has already been checked. If we are
1132 * the first tor reserve the device, we put the pool
1133 * name and pool type in the device record.
1135 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
1137 JCR *jcr = dcr->jcr;
1138 DEVICE *dev = dcr->dev;
1145 /* If device is being read, we cannot write it */
1146 if (dev->can_read()) {
1147 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
1148 jcr->JobId, dev->print_name());
1149 Dmsg1(dbglvl, "%s", jcr->errmsg);
1150 queue_reserve_message(jcr);
1154 /* If device is unmounted, we are out of luck */
1155 if (is_device_unmounted(dev)) {
1156 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
1157 jcr->JobId, dev->print_name());
1158 Dmsg1(dbglvl, "%s", jcr->errmsg);
1159 queue_reserve_message(jcr);
1163 Dmsg2(dbglvl, "JobId=%u reserve_append device is %s\n",
1164 (int)jcr->JobId, dev->print_name());
1166 /* Now do detailed tests ... */
1167 if (can_reserve_drive(dcr, rctx) != 1) {
1168 Dmsg1(dbglvl, "JobId=%u can_reserve_drive!=1\n", (int)jcr->JobId);
1172 dev->reserved_device++;
1173 Dmsg4(dbglvl, "JobId=%u Inc reserve=%d dev=%s %p\n", (int)jcr->JobId, dev->reserved_device,
1174 dev->print_name(), dev);
1175 dcr->reserved_device = true;
1184 * Returns: 1 if drive can be reserved
1185 * 0 if we should wait
1186 * -1 on error or impossibility
1188 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
1190 DEVICE *dev = dcr->dev;
1191 JCR *jcr = dcr->jcr;
1193 Dmsg6(dbglvl, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
1195 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1196 rctx.autochanger_only, rctx.any_drive);
1198 /* setting any_drive overrides PreferMountedVols flag */
1199 if (!rctx.any_drive) {
1201 * When PreferMountedVols is set, we keep track of the
1202 * drive in use that has the least number of writers, then if
1203 * no unmounted drive is found, we try that drive. This
1204 * helps spread the load to the least used drives.
1206 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
1207 Dmsg3(dbglvl, "OK dev=%s == low_drive=%s. JobId=%u\n",
1208 dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
1211 /* If he wants a free drive, but this one is busy, no go */
1212 if (!rctx.PreferMountedVols && dev->is_busy()) {
1213 /* Save least used drive */
1214 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
1215 rctx.num_writers = dev->num_writers + dev->reserved_device;
1216 rctx.low_use_drive = dev;
1217 Dmsg3(dbglvl, "JobId=%u set low use drive=%s num_writers=%d\n",
1218 (int)jcr->JobId, dev->print_name(), rctx.num_writers);
1220 Dmsg2(dbglvl, "JobId=%u not low use num_writers=%d\n",
1221 (int)jcr->JobId, dev->num_writers+dev->reserved_device);
1223 Dmsg1(dbglvl, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
1224 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
1225 jcr->JobId, dev->print_name());
1226 queue_reserve_message(jcr);
1230 /* Check for prefer mounted volumes */
1231 // if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
1232 if (rctx.PreferMountedVols && !dev->vol && dev->is_tape()) {
1233 Mmsg(jcr->errmsg, _("3606 JobId=%u prefers mounted drives, but drive %s has no Volume.\n"),
1234 jcr->JobId, dev->print_name());
1235 queue_reserve_message(jcr);
1236 Dmsg1(dbglvl, "failed: want mounted -- no vol JobId=%u\n", (uint32_t)jcr->JobId);
1237 return 0; /* No volume mounted */
1240 /* Check for exact Volume name match */
1241 /* ***FIXME*** for Disk, we can accept any volume that goes with this
1244 if (rctx.exact_match && rctx.have_volume) {
1246 Dmsg6(dbglvl, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
1248 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1249 rctx.autochanger_only, rctx.any_drive);
1250 Dmsg5(dbglvl, "JobId=%u have_vol=%d have=%s resvol=%s want=%s\n",
1251 (int)jcr->JobId, rctx.have_volume, dev->VolHdr.VolumeName,
1252 dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName);
1253 ok = strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) == 0 ||
1254 (dev->vol && strcmp(dev->vol->vol_name, rctx.VolumeName) == 0);
1256 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
1257 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
1259 queue_reserve_message(jcr);
1260 Dmsg4(dbglvl, "JobId=%u failed: dev have=%s resvol=%s want=%s\n",
1261 (int)jcr->JobId, dev->VolHdr.VolumeName,
1262 dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName);
1265 if (is_volume_in_use(dcr)) {
1266 return 0; /* fail if volume on another drive */
1271 /* Check for unused autochanger drive */
1272 if (rctx.autochanger_only && !dev->is_busy() &&
1273 dev->VolHdr.VolumeName[0] == 0) {
1274 /* Device is available but not yet reserved, reserve it for us */
1275 Dmsg2(dbglvl, "OK Res Unused autochanger %s JobId=%u.\n",
1276 dev->print_name(), jcr->JobId);
1277 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1278 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1279 return 1; /* reserve drive */
1283 * Handle the case that there are no writers
1285 if (dev->num_writers == 0) {
1286 /* Now check if there are any reservations on the drive */
1287 if (dev->reserved_device) {
1288 /* Now check if we want the same Pool and pool type */
1289 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1290 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1291 /* OK, compatible device */
1292 Dmsg2(dbglvl, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
1293 dev->print_name(), jcr->JobId);
1296 /* Drive Pool not suitable for us */
1297 Mmsg(jcr->errmsg, _(
1298 "3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"),
1299 jcr->JobId, dcr->pool_name, dev->pool_name,
1300 dev->reserved_device, dev->print_name());
1301 queue_reserve_message(jcr);
1302 Dmsg3(dbglvl, "JobId=%u failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
1303 (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1304 return 0; /* wait */
1306 } else if (dev->can_append()) {
1307 /* Device in append mode, check if changing pool */
1308 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1309 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1310 Dmsg2(dbglvl, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
1311 dev->print_name(), jcr->JobId);
1312 /* OK, compatible device */
1315 /* Changing pool, unload old tape if any in drive */
1316 Dmsg1(dbglvl, "JobId=%u OK dev: num_writers=0, not reserved, pool change, unload changer\n",
1318 unload_autochanger(dcr, 0);
1321 /* Device is available but not yet reserved, reserve it for us */
1322 Dmsg2(dbglvl, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
1324 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1325 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1326 return 1; /* reserve drive */
1330 * Check if the device is in append mode with writers (i.e.
1331 * available if pool is the same).
1333 if (dev->can_append() || dev->num_writers > 0) {
1334 /* Yes, now check if we want the same Pool and pool type */
1335 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1336 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1337 Dmsg2(dbglvl, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
1338 dev->print_name(), jcr->JobId);
1339 /* OK, compatible device */
1342 /* Drive Pool not suitable for us */
1343 Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but has Pool=\"%s\" on drive %s.\n"),
1344 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
1345 queue_reserve_message(jcr);
1346 Dmsg3(dbglvl, "JobId=%u failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
1347 (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1348 return 0; /* wait */
1351 Pmsg1(000, _("Logic error!!!! JobId=%u Should not get here.\n"), (int)jcr->JobId);
1352 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
1353 jcr->JobId, dev->print_name());
1354 queue_reserve_message(jcr);
1355 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
1356 return -1; /* error, should not get here */
1358 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
1359 jcr->JobId, dev->print_name());
1360 queue_reserve_message(jcr);
1361 Dmsg2(dbglvl, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
1366 * search_lock is already set on entering this routine
1368 static void queue_reserve_message(JCR *jcr)
1371 alist *msgs = jcr->reserve_msgs;
1378 * Look for duplicate message. If found, do
1381 for (i=msgs->size()-1; i >= 0; i--) {
1382 msg = (char *)msgs->get(i);
1386 /* Comparison based on 4 digit message number */
1387 if (strncmp(msg, jcr->errmsg, 4) == 0) {
1391 /* Message unique, so insert it */
1392 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1396 * Send any reservation messages queued for this jcr
1398 void send_drive_reserve_messages(JCR *jcr, void sendit(const char *msg, int len, void *sarg), void *arg)
1404 lock_reservations();
1405 msgs = jcr->reserve_msgs;
1406 if (!msgs || msgs->size() == 0) {
1409 for (i=msgs->size()-1; i >= 0; i--) {
1410 msg = (char *)msgs->get(i);
1412 sendit(" ", 3, arg);
1413 sendit(msg, strlen(msg), arg);
1420 unlock_reservations();