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 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 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 available 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;
1033 * If there is at least one volume that is valid and in use,
1034 * but we get here, check if we are running with prefers
1035 * non-mounted drives. In that case, we have selected a
1036 * non-used drive and our one and only volume is mounted
1037 * elsewhere, so we bail out and retry using that drive.
1039 if (dcr->volume_in_use && !rctx.PreferMountedVols) {
1040 rctx.PreferMountedVols = true;
1045 ok = reserve_device_for_append(dcr, rctx);
1047 rctx.jcr->dcr = dcr;
1048 Dmsg6(dbglvl, "JobId=%u Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
1049 (int)rctx.jcr->JobId,
1050 dcr->dev->reserved_device,
1051 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
1054 ok = reserve_device_for_read(dcr);
1056 rctx.jcr->read_dcr = dcr;
1057 Dmsg6(dbglvl, "JobId=%u Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
1058 (int)rctx.jcr->JobId,
1059 dcr->dev->reserved_device,
1060 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
1066 if (rctx.notify_dir) {
1068 BSOCK *dir = rctx.jcr->dir_bsock;
1069 pm_strcpy(dev_name, rctx.device->hdr.name);
1070 bash_spaces(dev_name);
1071 ok = dir->fsend(OK_device, dev_name.c_str()); /* Return real device name */
1072 Dmsg1(dbglvl, ">dird changer: %s", dir->msg);
1079 rctx.have_volume = false;
1081 Dmsg1(dbglvl, "JobId=%u Not OK.\n", (int)rctx.jcr->JobId);
1086 * We "reserve" the drive by setting the ST_READ bit. No one else
1087 * should touch the drive until that is cleared.
1088 * This allows the DIR to "reserve" the device before actually
1091 static bool reserve_device_for_read(DCR *dcr)
1093 DEVICE *dev = dcr->dev;
1094 JCR *jcr = dcr->jcr;
1101 if (is_device_unmounted(dev)) {
1102 Dmsg2(dbglvl, "JobId=%u Device %s is BLOCKED due to user unmount.\n",
1103 (int)jcr->JobId, dev->print_name());
1104 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
1105 jcr->JobId, dev->print_name());
1106 queue_reserve_message(jcr);
1110 if (dev->is_busy()) {
1111 Dmsg5(dbglvl, "JobId=%u Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n",
1112 (int)jcr->JobId, dev->print_name(),
1113 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
1114 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
1115 jcr->JobId, dev->print_name());
1116 queue_reserve_message(jcr);
1120 dev->clear_append();
1123 dev->reserved_device++;
1124 Dmsg4(dbglvl, "JobId=%u Inc reserve=%d dev=%s %p\n", (int)jcr->JobId,
1125 dev->reserved_device, dev->print_name(), dev);
1126 dcr->reserved_device = true;
1135 * We reserve the device for appending by incrementing the
1136 * reserved_device. We do virtually all the same work that
1137 * is done in acquire_device_for_append(), but we do
1138 * not attempt to mount the device. This routine allows
1139 * the DIR to reserve multiple devices before *really*
1140 * starting the job. It also permits the SD to refuse
1141 * certain devices (not up, ...).
1143 * Note, in reserving a device, if the device is for the
1144 * same pool and the same pool type, then it is acceptable.
1145 * The Media Type has already been checked. If we are
1146 * the first tor reserve the device, we put the pool
1147 * name and pool type in the device record.
1149 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
1151 JCR *jcr = dcr->jcr;
1152 DEVICE *dev = dcr->dev;
1159 /* If device is being read, we cannot write it */
1160 if (dev->can_read()) {
1161 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
1162 jcr->JobId, dev->print_name());
1163 Dmsg1(dbglvl, "%s", jcr->errmsg);
1164 queue_reserve_message(jcr);
1168 /* If device is unmounted, we are out of luck */
1169 if (is_device_unmounted(dev)) {
1170 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
1171 jcr->JobId, dev->print_name());
1172 Dmsg1(dbglvl, "%s", jcr->errmsg);
1173 queue_reserve_message(jcr);
1177 Dmsg2(dbglvl, "JobId=%u reserve_append device is %s\n",
1178 (int)jcr->JobId, dev->print_name());
1180 /* Now do detailed tests ... */
1181 if (can_reserve_drive(dcr, rctx) != 1) {
1182 Dmsg1(dbglvl, "JobId=%u can_reserve_drive!=1\n", (int)jcr->JobId);
1186 dev->reserved_device++;
1187 Dmsg4(dbglvl, "JobId=%u Inc reserve=%d dev=%s %p\n", (int)jcr->JobId, dev->reserved_device,
1188 dev->print_name(), dev);
1189 dcr->reserved_device = true;
1198 * Returns: 1 if drive can be reserved
1199 * 0 if we should wait
1200 * -1 on error or impossibility
1202 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
1204 DEVICE *dev = dcr->dev;
1205 JCR *jcr = dcr->jcr;
1207 Dmsg6(dbglvl, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
1209 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1210 rctx.autochanger_only, rctx.any_drive);
1212 /* setting any_drive overrides PreferMountedVols flag */
1213 if (!rctx.any_drive) {
1215 * When PreferMountedVols is set, we keep track of the
1216 * drive in use that has the least number of writers, then if
1217 * no unmounted drive is found, we try that drive. This
1218 * helps spread the load to the least used drives.
1220 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
1221 Dmsg3(dbglvl, "OK dev=%s == low_drive=%s. JobId=%u\n",
1222 dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
1225 /* If he wants a free drive, but this one is busy, no go */
1226 if (!rctx.PreferMountedVols && dev->is_busy()) {
1227 /* Save least used drive */
1228 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
1229 rctx.num_writers = dev->num_writers + dev->reserved_device;
1230 rctx.low_use_drive = dev;
1231 Dmsg3(dbglvl, "JobId=%u set low use drive=%s num_writers=%d\n",
1232 (int)jcr->JobId, dev->print_name(), rctx.num_writers);
1234 Dmsg2(dbglvl, "JobId=%u not low use num_writers=%d\n",
1235 (int)jcr->JobId, dev->num_writers+dev->reserved_device);
1237 Dmsg1(dbglvl, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
1238 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
1239 jcr->JobId, dev->print_name());
1240 queue_reserve_message(jcr);
1244 /* Check for prefer mounted volumes */
1245 if (rctx.PreferMountedVols && !dev->vol && dev->is_tape()) {
1246 Mmsg(jcr->errmsg, _("3606 JobId=%u prefers mounted drives, but drive %s has no Volume.\n"),
1247 jcr->JobId, dev->print_name());
1248 queue_reserve_message(jcr);
1249 Dmsg1(dbglvl, "failed: want mounted -- no vol JobId=%u\n", (uint32_t)jcr->JobId);
1250 return 0; /* No volume mounted */
1253 /* Check for exact Volume name match */
1254 /* ***FIXME*** for Disk, we can accept any volume that goes with this
1257 if (rctx.exact_match && rctx.have_volume) {
1259 Dmsg6(dbglvl, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
1261 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1262 rctx.autochanger_only, rctx.any_drive);
1263 Dmsg5(dbglvl, "JobId=%u have_vol=%d have=%s resvol=%s want=%s\n",
1264 (int)jcr->JobId, rctx.have_volume, dev->VolHdr.VolumeName,
1265 dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName);
1266 ok = strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) == 0 ||
1267 (dev->vol && strcmp(dev->vol->vol_name, rctx.VolumeName) == 0);
1269 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
1270 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
1272 queue_reserve_message(jcr);
1273 Dmsg4(dbglvl, "JobId=%u not OK: dev have=%s resvol=%s want=%s\n",
1274 (int)jcr->JobId, dev->VolHdr.VolumeName,
1275 dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName);
1278 if (is_volume_in_use(dcr)) {
1279 return 0; /* fail if volume on another drive */
1284 /* Check for unused autochanger drive */
1285 if (rctx.autochanger_only && !dev->is_busy() &&
1286 dev->VolHdr.VolumeName[0] == 0) {
1287 /* Device is available but not yet reserved, reserve it for us */
1288 Dmsg2(dbglvl, "OK Res Unused autochanger %s JobId=%u.\n",
1289 dev->print_name(), jcr->JobId);
1290 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1291 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1292 return 1; /* reserve drive */
1296 * Handle the case that there are no writers
1298 if (dev->num_writers == 0) {
1299 /* Now check if there are any reservations on the drive */
1300 if (dev->reserved_device) {
1301 /* Now check if we want the same Pool and pool type */
1302 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1303 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1304 /* OK, compatible device */
1305 Dmsg2(dbglvl, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
1306 dev->print_name(), jcr->JobId);
1309 /* Drive Pool not suitable for us */
1310 Mmsg(jcr->errmsg, _(
1311 "3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"),
1312 jcr->JobId, dcr->pool_name, dev->pool_name,
1313 dev->reserved_device, dev->print_name());
1314 queue_reserve_message(jcr);
1315 Dmsg3(dbglvl, "JobId=%u failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
1316 (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1317 return 0; /* wait */
1319 } else if (dev->can_append()) {
1320 /* Device in append mode, check if changing pool */
1321 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1322 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1323 Dmsg2(dbglvl, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
1324 dev->print_name(), jcr->JobId);
1325 /* OK, compatible device */
1328 /* Changing pool, unload old tape if any in drive */
1329 Dmsg1(dbglvl, "JobId=%u OK dev: num_writers=0, not reserved, pool change, unload changer\n",
1331 unload_autochanger(dcr, 0);
1334 /* Device is available but not yet reserved, reserve it for us */
1335 Dmsg2(dbglvl, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
1337 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1338 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1339 return 1; /* reserve drive */
1343 * Check if the device is in append mode with writers (i.e.
1344 * available if pool is the same).
1346 if (dev->can_append() || dev->num_writers > 0) {
1347 /* Yes, now check if we want the same Pool and pool type */
1348 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1349 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1350 Dmsg2(dbglvl, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
1351 dev->print_name(), jcr->JobId);
1352 /* OK, compatible device */
1355 /* Drive Pool not suitable for us */
1356 Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but has Pool=\"%s\" on drive %s.\n"),
1357 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
1358 queue_reserve_message(jcr);
1359 Dmsg3(dbglvl, "JobId=%u failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
1360 (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1361 return 0; /* wait */
1364 Pmsg1(000, _("Logic error!!!! JobId=%u Should not get here.\n"), (int)jcr->JobId);
1365 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
1366 jcr->JobId, dev->print_name());
1367 queue_reserve_message(jcr);
1368 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
1369 return -1; /* error, should not get here */
1371 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
1372 jcr->JobId, dev->print_name());
1373 queue_reserve_message(jcr);
1374 Dmsg2(dbglvl, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
1379 * search_lock is already set on entering this routine
1381 static void queue_reserve_message(JCR *jcr)
1384 alist *msgs = jcr->reserve_msgs;
1391 * Look for duplicate message. If found, do
1394 for (i=msgs->size()-1; i >= 0; i--) {
1395 msg = (char *)msgs->get(i);
1399 /* Comparison based on 4 digit message number */
1400 if (strncmp(msg, jcr->errmsg, 4) == 0) {
1404 /* Message unique, so insert it */
1405 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1409 * Send any reservation messages queued for this jcr
1411 void send_drive_reserve_messages(JCR *jcr, void sendit(const char *msg, int len, void *sarg), void *arg)
1417 lock_reservations();
1418 msgs = jcr->reserve_msgs;
1419 if (!msgs || msgs->size() == 0) {
1422 for (i=msgs->size()-1; i >= 0; i--) {
1423 msg = (char *)msgs->get(i);
1425 sendit(" ", 3, arg);
1426 sendit(msg, strlen(msg), arg);
1433 unlock_reservations();