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);
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 vol cannot 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 cannot 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 Dmsg1(dbglvl, "JobId=%u duplicate vol list\n", (int)rctx.jcr->JobId);
805 temp_vol_list = New(dlist(vol, &vol->link));
806 foreach_dlist(vol, vol_list) {
808 VOLRES *tvol = (VOLRES *)malloc(sizeof(VOLRES));
809 memset(tvol, 0, sizeof(VOLRES));
810 tvol->vol_name = bstrdup(vol->vol_name);
811 tvol->dev = vol->dev;
812 nvol = (VOLRES *)temp_vol_list->binary_insert(tvol, my_compare);
814 tvol->dev = NULL; /* don't zap dev entry */
816 Pmsg0(000, "Logic error. Duplicating vol list hit duplicate.\n");
817 Jmsg(jcr, M_WARNING, 0, "Logic error. Duplicating vol list hit duplicate.\n");
822 /* Look through reserved volumes for one we can use */
823 foreach_dlist(vol, temp_vol_list) {
827 foreach_alist(store, dirstore) {
829 foreach_alist(device_name, store->device) {
831 if (strcmp(device_name, vol->dev->device->hdr.name) != 0) {
834 rctx.device_name = device_name;
835 rctx.device = vol->dev->device;
836 bstrncpy(rctx.VolumeName, vol->vol_name, sizeof(rctx.VolumeName));
837 rctx.have_volume = true;
838 /* Try reserving this device and volume */
839 Dmsg3(dbglvl, "JobId=%u try vol=%s on device=%s\n", (int)rctx.jcr->JobId,
840 rctx.VolumeName, device_name);
841 stat = reserve_device(rctx);
842 if (stat == 1) { /* found available device */
843 Dmsg2(dbglvl, "JobId=%u Suitable device found=%s\n", (int)rctx.jcr->JobId,
847 } else if (stat == 0) { /* device busy */
848 Dmsg2(dbglvl, "JobId=%u Suitable device=%s, busy: not use\n",
849 (int)rctx.jcr->JobId, device_name);
851 /* otherwise error */
852 Dmsg1(dbglvl, "JobId=%u No suitable device found.\n", (int)rctx.jcr->JobId);
854 rctx.have_volume = false;
860 } /* end for loop over reserved volumes */
862 save_vol_list = vol_list;
863 vol_list = temp_vol_list;
864 free_volume_list(); /* release temp_vol_list */
865 vol_list = save_vol_list;
866 Dmsg1(dbglvl, "JobId=%u deleted temp vol list\n", (int)rctx.jcr->JobId);
870 Dmsg2(dbglvl, "JobId=%u got vol %s in reserved volums list\n", (int)rctx.jcr->JobId,
876 * No reserved volume we can use, so now search for an available device.
878 * For each storage device that the user specified, we
879 * search and see if there is a resource for that device.
881 foreach_alist(store, dirstore) {
883 foreach_alist(device_name, store->device) {
885 rctx.device_name = device_name;
886 stat = search_res_for_device(rctx);
887 if (stat == 1) { /* found available device */
888 Dmsg2(dbglvl, "JobId=%u available device found=%s\n", (int)rctx.jcr->JobId,
892 } else if (stat == 0) { /* device busy */
893 Dmsg2(dbglvl, "JobId=%u Suitable device=%s, busy: not use\n",
894 (int)rctx.jcr->JobId, device_name);
896 /* otherwise error */
897 Dmsg1(dbglvl, "JobId=%u No suitable device found.\n", (int)rctx.jcr->JobId);
908 * Search for a particular storage device with particular storage
909 * characteristics (MediaType).
911 int search_res_for_device(RCTX &rctx)
913 AUTOCHANGER *changer;
916 Dmsg2(dbglvl, "JobId=%u search res for %s\n", (int)rctx.jcr->JobId, rctx.device_name);
917 /* Look through Autochangers first */
918 foreach_res(changer, R_AUTOCHANGER) {
919 Dmsg2(150, "JobId=%u Try match changer res=%s\n", (int)rctx.jcr->JobId, changer->hdr.name);
920 /* Find resource, and make sure we were able to open it */
921 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
922 /* Try each device in this AutoChanger */
923 foreach_alist(rctx.device, changer->device) {
924 Dmsg2(dbglvl, "JobId=%u Try changer device %s\n", (int)rctx.jcr->JobId,
925 rctx.device->hdr.name);
926 stat = reserve_device(rctx);
927 if (stat != 1) { /* try another device */
931 if (rctx.store->append == SD_APPEND) {
932 Dmsg3(dbglvl, "JobId=%u Device %s reserved=%d for append.\n",
933 (int)rctx.jcr->JobId, rctx.device->hdr.name,
934 rctx.jcr->dcr->dev->reserved_device);
936 Dmsg3(dbglvl, "JobId=%u Device %s reserved=%d for read.\n",
937 (int)rctx.jcr->JobId, rctx.device->hdr.name,
938 rctx.jcr->read_dcr->dev->reserved_device);
945 /* Now if requested look through regular devices */
946 if (!rctx.autochanger_only) {
947 foreach_res(rctx.device, R_DEVICE) {
948 Dmsg2(150, "JobId=%u Try match res=%s\n", (int)rctx.jcr->JobId, rctx.device->hdr.name);
949 /* Find resource, and make sure we were able to open it */
950 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
951 stat = reserve_device(rctx);
952 if (stat != 1) { /* try another device */
956 if (rctx.store->append == SD_APPEND) {
957 Dmsg3(dbglvl, "JobId=%u Device %s reserved=%d for append.\n",
958 (int)rctx.jcr->JobId, rctx.device->hdr.name,
959 rctx.jcr->dcr->dev->reserved_device);
961 Dmsg3(dbglvl, "JobId=%u Device %s reserved=%d for read.\n",
962 (int)rctx.jcr->JobId, rctx.device->hdr.name,
963 rctx.jcr->read_dcr->dev->reserved_device);
969 return -1; /* nothing found */
973 * Try to reserve a specific device.
975 * Returns: 1 -- OK, have DCR
979 static int reserve_device(RCTX &rctx)
983 const int name_len = MAX_NAME_LENGTH;
985 /* Make sure MediaType is OK */
986 Dmsg3(dbglvl, "JobId=%u chk MediaType device=%s request=%s\n",
987 (int)rctx.jcr->JobId,
988 rctx.device->media_type, rctx.store->media_type);
989 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
993 /* Make sure device exists -- i.e. we can stat() it */
994 if (!rctx.device->dev) {
995 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
997 if (!rctx.device->dev) {
998 if (rctx.device->changer_res) {
999 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
1000 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
1001 rctx.device->hdr.name, rctx.device_name);
1003 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
1004 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
1007 return -1; /* no use waiting */
1010 rctx.suitable_device = true;
1011 Dmsg2(dbglvl, "JobId=%u try reserve %s\n", rctx.jcr->JobId, rctx.device->hdr.name);
1012 dcr = new_dcr(rctx.jcr, rctx.device->dev);
1014 BSOCK *dir = rctx.jcr->dir_bsock;
1015 dir->fsend(_("3926 Could not get dcr for device: %s\n"), rctx.device_name);
1016 Dmsg1(dbglvl, ">dird: %s", dir->msg);
1019 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
1020 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
1021 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
1022 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
1023 if (rctx.store->append == SD_APPEND) {
1024 Dmsg3(dbglvl, "JobId=%u have_vol=%d vol=%s\n", (int)rctx.jcr->JobId,
1025 rctx.have_volume, rctx.VolumeName);
1026 if (!rctx.have_volume) {
1027 dcr->any_volume = true;
1028 if (dir_find_next_appendable_volume(dcr)) {
1029 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
1030 Dmsg2(dbglvl, "JobId=%u looking for Volume=%s\n", (int)rctx.jcr->JobId, rctx.VolumeName);
1031 rctx.have_volume = true;
1033 Dmsg1(dbglvl, "JobId=%u No next volume found\n", (int)rctx.jcr->JobId);
1034 rctx.have_volume = false;
1035 rctx.VolumeName[0] = 0;
1037 * If there is at least one volume that is valid and in use,
1038 * but we get here, check if we are running with prefers
1039 * non-mounted drives. In that case, we have selected a
1040 * non-used drive and our one and only volume is mounted
1041 * elsewhere, so we bail out and retry using that drive.
1043 if (dcr->volume_in_use && !rctx.PreferMountedVols) {
1044 rctx.PreferMountedVols = true;
1049 ok = reserve_device_for_append(dcr, rctx);
1051 rctx.jcr->dcr = dcr;
1052 Dmsg6(dbglvl, "JobId=%u Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
1053 (int)rctx.jcr->JobId,
1054 dcr->dev->reserved_device,
1055 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
1058 ok = reserve_device_for_read(dcr);
1060 rctx.jcr->read_dcr = dcr;
1061 Dmsg6(dbglvl, "JobId=%u Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
1062 (int)rctx.jcr->JobId,
1063 dcr->dev->reserved_device,
1064 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
1070 if (rctx.notify_dir) {
1072 BSOCK *dir = rctx.jcr->dir_bsock;
1073 pm_strcpy(dev_name, rctx.device->hdr.name);
1074 bash_spaces(dev_name);
1075 ok = dir->fsend(OK_device, dev_name.c_str()); /* Return real device name */
1076 Dmsg1(dbglvl, ">dird changer: %s", dir->msg);
1083 rctx.have_volume = false;
1085 Dmsg1(dbglvl, "JobId=%u Not OK.\n", (int)rctx.jcr->JobId);
1090 * We "reserve" the drive by setting the ST_READ bit. No one else
1091 * should touch the drive until that is cleared.
1092 * This allows the DIR to "reserve" the device before actually
1095 static bool reserve_device_for_read(DCR *dcr)
1097 DEVICE *dev = dcr->dev;
1098 JCR *jcr = dcr->jcr;
1105 if (is_device_unmounted(dev)) {
1106 Dmsg2(dbglvl, "JobId=%u Device %s is BLOCKED due to user unmount.\n",
1107 (int)jcr->JobId, dev->print_name());
1108 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
1109 jcr->JobId, dev->print_name());
1110 queue_reserve_message(jcr);
1114 if (dev->is_busy()) {
1115 Dmsg5(dbglvl, "JobId=%u Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n",
1116 (int)jcr->JobId, dev->print_name(),
1117 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
1118 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
1119 jcr->JobId, dev->print_name());
1120 queue_reserve_message(jcr);
1124 dev->clear_append();
1127 dev->reserved_device++;
1128 Dmsg4(dbglvl, "JobId=%u Inc reserve=%d dev=%s %p\n", (int)jcr->JobId,
1129 dev->reserved_device, dev->print_name(), dev);
1130 dcr->reserved_device = true;
1139 * We reserve the device for appending by incrementing the
1140 * reserved_device. We do virtually all the same work that
1141 * is done in acquire_device_for_append(), but we do
1142 * not attempt to mount the device. This routine allows
1143 * the DIR to reserve multiple devices before *really*
1144 * starting the job. It also permits the SD to refuse
1145 * certain devices (not up, ...).
1147 * Note, in reserving a device, if the device is for the
1148 * same pool and the same pool type, then it is acceptable.
1149 * The Media Type has already been checked. If we are
1150 * the first tor reserve the device, we put the pool
1151 * name and pool type in the device record.
1153 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
1155 JCR *jcr = dcr->jcr;
1156 DEVICE *dev = dcr->dev;
1163 /* If device is being read, we cannot write it */
1164 if (dev->can_read()) {
1165 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
1166 jcr->JobId, dev->print_name());
1167 Dmsg1(dbglvl, "%s", jcr->errmsg);
1168 queue_reserve_message(jcr);
1172 /* If device is unmounted, we are out of luck */
1173 if (is_device_unmounted(dev)) {
1174 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
1175 jcr->JobId, dev->print_name());
1176 Dmsg1(dbglvl, "%s", jcr->errmsg);
1177 queue_reserve_message(jcr);
1181 Dmsg2(dbglvl, "JobId=%u reserve_append device is %s\n",
1182 (int)jcr->JobId, dev->print_name());
1184 /* Now do detailed tests ... */
1185 if (can_reserve_drive(dcr, rctx) != 1) {
1186 Dmsg1(dbglvl, "JobId=%u can_reserve_drive!=1\n", (int)jcr->JobId);
1190 dev->reserved_device++;
1191 Dmsg4(dbglvl, "JobId=%u Inc reserve=%d dev=%s %p\n", (int)jcr->JobId, dev->reserved_device,
1192 dev->print_name(), dev);
1193 dcr->reserved_device = true;
1202 * Returns: 1 if drive can be reserved
1203 * 0 if we should wait
1204 * -1 on error or impossibility
1206 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
1208 DEVICE *dev = dcr->dev;
1209 JCR *jcr = dcr->jcr;
1211 Dmsg6(dbglvl, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
1213 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1214 rctx.autochanger_only, rctx.any_drive);
1216 /* setting any_drive overrides PreferMountedVols flag */
1217 if (!rctx.any_drive) {
1219 * When PreferMountedVols is set, we keep track of the
1220 * drive in use that has the least number of writers, then if
1221 * no unmounted drive is found, we try that drive. This
1222 * helps spread the load to the least used drives.
1224 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
1225 Dmsg3(dbglvl, "OK dev=%s == low_drive=%s. JobId=%u\n",
1226 dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
1229 /* If he wants a free drive, but this one is busy, no go */
1230 if (!rctx.PreferMountedVols && dev->is_busy()) {
1231 /* Save least used drive */
1232 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
1233 rctx.num_writers = dev->num_writers + dev->reserved_device;
1234 rctx.low_use_drive = dev;
1235 Dmsg3(dbglvl, "JobId=%u set low use drive=%s num_writers=%d\n",
1236 (int)jcr->JobId, dev->print_name(), rctx.num_writers);
1238 Dmsg2(dbglvl, "JobId=%u not low use num_writers=%d\n",
1239 (int)jcr->JobId, dev->num_writers+dev->reserved_device);
1241 Dmsg1(dbglvl, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
1242 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
1243 jcr->JobId, dev->print_name());
1244 queue_reserve_message(jcr);
1248 /* Check for prefer mounted volumes */
1249 if (rctx.PreferMountedVols && !dev->vol && dev->is_tape()) {
1250 Mmsg(jcr->errmsg, _("3606 JobId=%u prefers mounted drives, but drive %s has no Volume.\n"),
1251 jcr->JobId, dev->print_name());
1252 queue_reserve_message(jcr);
1253 Dmsg1(dbglvl, "failed: want mounted -- no vol JobId=%u\n", (uint32_t)jcr->JobId);
1254 return 0; /* No volume mounted */
1257 /* Check for exact Volume name match */
1258 /* ***FIXME*** for Disk, we can accept any volume that goes with this
1261 if (rctx.exact_match && rctx.have_volume) {
1263 Dmsg6(dbglvl, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
1265 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1266 rctx.autochanger_only, rctx.any_drive);
1267 Dmsg5(dbglvl, "JobId=%u have_vol=%d have=%s resvol=%s want=%s\n",
1268 (int)jcr->JobId, rctx.have_volume, dev->VolHdr.VolumeName,
1269 dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName);
1270 ok = strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) == 0 ||
1271 (dev->vol && strcmp(dev->vol->vol_name, rctx.VolumeName) == 0);
1273 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
1274 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
1276 queue_reserve_message(jcr);
1277 Dmsg4(dbglvl, "JobId=%u not OK: dev have=%s resvol=%s want=%s\n",
1278 (int)jcr->JobId, dev->VolHdr.VolumeName,
1279 dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName);
1282 if (is_volume_in_use(dcr)) {
1283 return 0; /* fail if volume on another drive */
1288 /* Check for unused autochanger drive */
1289 if (rctx.autochanger_only && !dev->is_busy() &&
1290 dev->VolHdr.VolumeName[0] == 0) {
1291 /* Device is available but not yet reserved, reserve it for us */
1292 Dmsg2(dbglvl, "OK Res Unused autochanger %s JobId=%u.\n",
1293 dev->print_name(), jcr->JobId);
1294 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1295 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1296 return 1; /* reserve drive */
1300 * Handle the case that there are no writers
1302 if (dev->num_writers == 0) {
1303 /* Now check if there are any reservations on the drive */
1304 if (dev->reserved_device) {
1305 /* Now check if we want the same Pool and pool type */
1306 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1307 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1308 /* OK, compatible device */
1309 Dmsg2(dbglvl, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
1310 dev->print_name(), jcr->JobId);
1313 /* Drive Pool not suitable for us */
1314 Mmsg(jcr->errmsg, _(
1315 "3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"),
1316 jcr->JobId, dcr->pool_name, dev->pool_name,
1317 dev->reserved_device, dev->print_name());
1318 queue_reserve_message(jcr);
1319 Dmsg3(dbglvl, "JobId=%u failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
1320 (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1321 return 0; /* wait */
1323 } else if (dev->can_append()) {
1324 /* Device in append mode, check if changing pool */
1325 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1326 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1327 Dmsg2(dbglvl, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
1328 dev->print_name(), jcr->JobId);
1329 /* OK, compatible device */
1332 /* Changing pool, unload old tape if any in drive */
1333 Dmsg1(dbglvl, "JobId=%u OK dev: num_writers=0, not reserved, pool change, unload changer\n",
1335 unload_autochanger(dcr, 0);
1338 /* Device is available but not yet reserved, reserve it for us */
1339 Dmsg2(dbglvl, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
1341 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1342 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1343 return 1; /* reserve drive */
1347 * Check if the device is in append mode with writers (i.e.
1348 * available if pool is the same).
1350 if (dev->can_append() || dev->num_writers > 0) {
1351 /* Yes, now check if we want the same Pool and pool type */
1352 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1353 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1354 Dmsg2(dbglvl, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
1355 dev->print_name(), jcr->JobId);
1356 /* OK, compatible device */
1359 /* Drive Pool not suitable for us */
1360 Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but has Pool=\"%s\" on drive %s.\n"),
1361 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
1362 queue_reserve_message(jcr);
1363 Dmsg3(dbglvl, "JobId=%u failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
1364 (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1365 return 0; /* wait */
1368 Pmsg1(000, _("Logic error!!!! JobId=%u Should not get here.\n"), (int)jcr->JobId);
1369 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
1370 jcr->JobId, dev->print_name());
1371 queue_reserve_message(jcr);
1372 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
1373 return -1; /* error, should not get here */
1375 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
1376 jcr->JobId, dev->print_name());
1377 queue_reserve_message(jcr);
1378 Dmsg2(dbglvl, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
1383 * search_lock is already set on entering this routine
1385 static void queue_reserve_message(JCR *jcr)
1388 alist *msgs = jcr->reserve_msgs;
1395 * Look for duplicate message. If found, do
1398 for (i=msgs->size()-1; i >= 0; i--) {
1399 msg = (char *)msgs->get(i);
1403 /* Comparison based on 4 digit message number */
1404 if (strncmp(msg, jcr->errmsg, 4) == 0) {
1408 /* Message unique, so insert it */
1409 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1413 * Send any reservation messages queued for this jcr
1415 void send_drive_reserve_messages(JCR *jcr, void sendit(const char *msg, int len, void *sarg), void *arg)
1421 lock_reservations();
1422 msgs = jcr->reserve_msgs;
1423 if (!msgs || msgs->size() == 0) {
1426 for (i=msgs->size()-1; i >= 0; i--) {
1427 msg = (char *)msgs->get(i);
1429 sendit(" ", 3, arg);
1430 sendit(msg, strlen(msg), arg);
1437 unlock_reservations();