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 static dlist *vol_list = NULL;
43 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
45 /* Forward referenced functions */
46 static int can_reserve_drive(DCR *dcr, RCTX &rctx);
47 static int reserve_device(RCTX &rctx);
48 static bool reserve_device_for_read(DCR *dcr);
49 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
50 static bool use_storage_cmd(JCR *jcr);
51 static void queue_reserve_message(JCR *jcr);
53 /* Requests from the Director daemon */
54 static char use_storage[] = "use storage=%127s media_type=%127s "
55 "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
56 static char use_device[] = "use device=%127s\n";
58 /* Responses sent to Director daemon */
59 static char OK_device[] = "3000 OK use device device=%s\n";
60 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
61 static char BAD_use[] = "3913 Bad use command: %s\n";
63 bool use_cmd(JCR *jcr)
66 * Get the device, media, and pool information
68 if (!use_storage_cmd(jcr)) {
69 set_jcr_job_status(jcr, JS_ErrorTerminated);
70 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
76 static int my_compare(void *item1, void *item2)
78 return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
81 static brwlock_t reservation_lock;
83 void init_reservations_lock()
86 if ((errstat=rwl_init(&reservation_lock)) != 0) {
88 Emsg1(M_ABORT, 0, _("Unable to initialize reservation lock. ERR=%s\n"),
89 be.strerror(errstat));
94 void term_reservations_lock()
96 rwl_destroy(&reservation_lock);
99 /* This applies to a drive and to Volumes */
100 void lock_reservations()
103 if ((errstat=rwl_writelock(&reservation_lock)) != 0) {
105 Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
106 errstat, be.strerror(errstat));
110 void unlock_reservations()
113 if ((errstat=rwl_writeunlock(&reservation_lock)) != 0) {
115 Emsg2(M_ABORT, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
116 errstat, be.strerror(errstat));
122 * Put a new Volume entry in the Volume list. This
123 * effectively reserves the volume so that it will
124 * not be mounted again.
126 * Return: VOLRES entry on success
127 * NULL if the Volume is already in the list
129 VOLRES *new_volume(DCR *dcr, const char *VolumeName)
133 Dmsg1(400, "new_volume %s\n", VolumeName);
135 * We lock the reservations system here to ensure
136 * when adding a new volume that no newly scheduled
137 * job can reserve it.
142 * First, if this dcr already is attached to any device,
143 * remove any old volumes attached to this device as they
144 * are no longer used (there should at max be one).
148 foreach_dlist(vol, vol_list) {
149 if (vol && vol->dev == dcr->dev) {
150 vol_list->remove(vol);
152 Dmsg1(100, "new_vol free vol=%s\n", vol->vol_name);
160 vol = (VOLRES *)malloc(sizeof(VOLRES));
161 memset(vol, 0, sizeof(VOLRES));
162 vol->vol_name = bstrdup(VolumeName);
165 Dmsg2(100, "New Vol=%s dev=%s\n", VolumeName, dcr->dev->print_name());
167 * Now try to insert the new Volume
169 nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
171 Dmsg2(100, "Found vol=%s same dcr=%d\n", nvol->vol_name, dcr==nvol->dcr);
173 * At this point, a Volume with this name already is in the
174 * list, free our temp structure
180 DEVICE *dev = nvol->dev;
181 /* ***FIXME*** don't we need a mutex here? */
182 if (!dev->is_busy()) {
183 Dmsg3(100, "Swap vol=%s from dev=%s to %s\n", VolumeName,
184 dev->print_name(), dcr->dev->print_name());
185 nvol->dev = dcr->dev;
186 dev->VolHdr.VolumeName[0] = 0;
188 Dmsg3(100, "Logic ERROR!!!! could not swap vol=%s from dev=%s to %s\n", VolumeName,
189 dev->print_name(), dcr->dev->print_name());
194 unlock_reservations();
199 * Search for a Volume name in the Volume list.
201 * Returns: VOLRES entry on success
202 * NULL if the Volume is not in the list
204 VOLRES *find_volume(const char *VolumeName)
207 /* Do not lock reservations here */
209 vol.vol_name = bstrdup(VolumeName);
210 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
213 Dmsg2(100, "find_vol=%s found=%d\n", VolumeName, fvol!=NULL);
218 * Free a Volume from the Volume list
220 * Returns: true if the Volume found and removed from the list
221 * false if the Volume is not in the list
223 bool free_volume(DEVICE *dev)
227 if (dev->VolHdr.VolumeName[0] == 0) {
233 Dmsg1(100, "free_volume: no vol on dev %s\n", dev->print_name());
235 * Our device has no VolumeName listed, but
236 * search the list for any Volume attached to
237 * this device and remove it.
239 foreach_dlist(fvol, vol_list) {
240 if (fvol && fvol->dev == dev) {
241 vol_list->remove(fvol);
242 if (fvol->vol_name) {
243 Dmsg2(100, "free_volume %s dev=%s\n", fvol->vol_name, dev->print_name());
244 free(fvol->vol_name);
253 Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
254 vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
255 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
257 vol_list->remove(fvol);
258 Dmsg2(100, "free_volume %s dev=%s\n", fvol->vol_name, dev->print_name());
259 free(fvol->vol_name);
263 // dev->VolHdr.VolumeName[0] = 0;
269 /* Free volume reserved by this dcr but not attached to a dev */
270 void free_unused_volume(DCR *dcr)
275 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
277 * Releease this volume, but only if we inserted it (same dcr) and
278 * it is not attached to a device or the Volume in the device is
280 * I wonder if this is right, kes ...
282 if (vol->dcr == dcr && (vol->dev == NULL ||
283 strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
284 vol_list->remove(vol);
285 Dmsg1(100, "free_unused_volume %s\n", vol->vol_name);
295 * List Volumes -- this should be moved to status.c
297 void list_volumes(void sendit(const char *msg, int len, void *sarg), void *arg)
303 msg = (char *)get_pool_memory(PM_MESSAGE);
306 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
308 len = Mmsg(msg, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
309 sendit(msg, len, arg);
311 len = Mmsg(msg, "%s\n", vol->vol_name);
312 sendit(msg, len, arg);
317 free_pool_memory(msg);
320 /* Create the Volume list */
321 void create_volume_list()
323 VOLRES *dummy = NULL;
324 if (vol_list == NULL) {
325 vol_list = New(dlist(dummy, &dummy->link));
329 /* Release all Volumes from the list */
330 void free_volume_list()
337 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
338 Dmsg3(100, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
346 bool is_volume_in_use(DCR *dcr)
348 VOLRES *vol = find_volume(dcr->VolumeName);
350 Dmsg1(100, "Vol=%s not in use.\n", dcr->VolumeName);
351 return false; /* vol not in list */
353 if (!vol->dev) { /* vol not attached to device */
354 Dmsg1(100, "Vol=%s has no dev.\n", dcr->VolumeName);
357 if (dcr->dev == vol->dev) { /* same device OK */
358 Dmsg1(100, "Vol=%s on same dev.\n", dcr->VolumeName);
361 if (!vol->dev->is_busy()) {
362 Dmsg2(100, "Vol=%s dev=%s not busy.\n", dcr->VolumeName, vol->dev->print_name());
365 Dmsg2(100, "Vol=%s used by %s.\n", dcr->VolumeName, vol->dev->print_name());
371 * We get the following type of information:
373 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
377 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
381 static bool use_storage_cmd(JCR *jcr)
383 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
384 BSOCK *dir = jcr->dir_bsock;
394 memset(&rctx, 0, sizeof(RCTX));
397 * If there are multiple devices, the director sends us
398 * use_device for each device that it wants to use.
400 dirstore = New(alist(10, not_owned_by_alist));
401 // Dmsg2(000, "dirstore=%p JobId=%u\n", dirstore, jcr->JobId);
402 msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
404 Dmsg1(100, "<dird: %s", dir->msg);
405 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
406 media_type.c_str(), pool_name.c_str(),
407 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
412 jcr->write_store = dirstore;
414 jcr->read_store = dirstore;
416 rctx.append = append;
417 unbash_spaces(store_name);
418 unbash_spaces(media_type);
419 unbash_spaces(pool_name);
420 unbash_spaces(pool_type);
421 store = new DIRSTORE;
422 dirstore->append(store);
423 memset(store, 0, sizeof(DIRSTORE));
424 store->device = New(alist(10));
425 bstrncpy(store->name, store_name, sizeof(store->name));
426 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
427 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
428 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
429 store->append = append;
431 /* Now get all devices */
432 while (dir->recv() >= 0) {
433 Dmsg1(100, "<dird device: %s", dir->msg);
434 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
438 unbash_spaces(dev_name);
439 store->device->append(bstrdup(dev_name.c_str()));
441 } while (ok && dir->recv() >= 0);
444 /* This loop is debug code and can be removed */
445 /* ***FIXME**** remove after 1.38 release */
447 foreach_alist(store, dirstore) {
448 Dmsg5(110, "Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n",
449 store->name, store->media_type, store->pool_name,
450 store->pool_type, store->append);
451 foreach_alist(device_name, store->device) {
452 Dmsg1(110, " Device=%s\n", device_name);
457 init_jcr_device_wait_timers(jcr);
459 * At this point, we have a list of all the Director's Storage
460 * resources indicated for this Job, which include Pool, PoolType,
461 * storage name, and Media type.
462 * Then for each of the Storage resources, we have a list of
463 * device names that were given.
465 * Wiffle through them and find one that can do the backup.
468 bool first = true; /* print wait message once */
470 rctx.notify_dir = true;
472 for ( ; !fail && !job_canceled(jcr); ) {
473 while ((msg = (char *)msgs->pop())) {
476 rctx.suitable_device = false;
477 rctx.have_volume = false;
478 rctx.any_drive = false;
479 if (!jcr->PreferMountedVols) {
480 /* Look for unused drives in autochangers */
481 rctx.num_writers = 20000000; /* start with impossible number */
482 rctx.low_use_drive = NULL;
483 rctx.PreferMountedVols = false;
484 rctx.exact_match = false;
485 rctx.autochanger_only = true;
486 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
487 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
488 rctx.autochanger_only, rctx.any_drive);
489 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
492 /* Look through all drives possibly for low_use drive */
493 if (rctx.low_use_drive) {
494 rctx.try_low_use_drive = true;
495 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
498 rctx.try_low_use_drive = false;
500 rctx.autochanger_only = false;
501 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
502 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
503 rctx.autochanger_only, rctx.any_drive);
504 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
508 /* Look for an exact match all drives */
509 rctx.PreferMountedVols = true;
510 rctx.exact_match = true;
511 rctx.autochanger_only = false;
512 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
513 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
514 rctx.autochanger_only, rctx.any_drive);
515 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
518 /* Look for any mounted drive */
519 rctx.exact_match = false;
520 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
521 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
522 rctx.autochanger_only, rctx.any_drive);
523 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
527 rctx.any_drive = true;
528 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
529 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
530 rctx.autochanger_only, rctx.any_drive);
531 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
534 /* Keep reservations locked *except* during wait_for_device() */
535 unlock_reservations();
536 if (!rctx.suitable_device || !wait_for_device(jcr, first)) {
537 Dmsg0(100, "Fail. !suitable_device || !wait_for_device\n");
542 bnet_sig(dir, BNET_HEARTBEAT); /* Inform Dir that we are alive */
544 unlock_reservations();
547 * If we get here, there are no suitable devices available, which
548 * means nothing configured. If a device is suitable but busy
549 * with another Volume, we will not come here.
551 unbash_spaces(dir->msg);
552 pm_strcpy(jcr->errmsg, dir->msg);
553 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
554 Jmsg(jcr, M_FATAL, 0, _("\n"
555 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
556 dev_name.c_str(), media_type.c_str());
557 bnet_fsend(dir, NO_device, dev_name.c_str());
559 Dmsg1(100, ">dird: %s", dir->msg);
562 unbash_spaces(dir->msg);
563 pm_strcpy(jcr->errmsg, dir->msg);
564 Jmsg(jcr, M_FATAL, 0, _("Failed command: %s\n"), jcr->errmsg);
565 bnet_fsend(dir, BAD_use, jcr->errmsg);
566 Dmsg1(100, ">dird: %s", dir->msg);
573 void release_msgs(JCR *jcr)
575 alist *msgs = jcr->reserve_msgs;
582 while ((msg = (char *)msgs->pop())) {
586 jcr->reserve_msgs = NULL;
587 unlock_reservations();
591 * Search for a device suitable for this job.
593 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
601 dirstore = jcr->write_store;
603 dirstore = jcr->read_store;
606 * For each storage device that the user specified, we
607 * search and see if there is a resource for that device.
609 Dmsg4(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
610 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
611 rctx.autochanger_only);
613 foreach_alist(store, dirstore) {
615 foreach_alist(device_name, store->device) {
617 rctx.device_name = device_name;
618 stat = search_res_for_device(rctx);
619 if (stat == 1) { /* found available device */
620 Dmsg1(100, "Suitable device found=%s\n", device_name);
623 } else if (stat == 0) { /* device busy */
624 Dmsg1(110, "Suitable device found=%s, not used: busy\n", device_name);
626 /* otherwise error */
627 Dmsg0(110, "No suitable device found.\n");
638 * Search for a particular storage device with particular storage
639 * characteristics (MediaType).
641 int search_res_for_device(RCTX &rctx)
643 AUTOCHANGER *changer;
644 BSOCK *dir = rctx.jcr->dir_bsock;
648 Dmsg1(110, "Search res for %s\n", rctx.device_name);
649 /* Look through Autochangers first */
650 foreach_res(changer, R_AUTOCHANGER) {
651 Dmsg1(150, "Try match changer res=%s\n", changer->hdr.name);
652 /* Find resource, and make sure we were able to open it */
653 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
654 /* Try each device in this AutoChanger */
655 foreach_alist(rctx.device, changer->device) {
656 Dmsg1(110, "Try changer device %s\n", rctx.device->hdr.name);
657 stat = reserve_device(rctx);
658 if (stat != 1) { /* try another device */
662 if (rctx.store->append == SD_APPEND) {
663 Dmsg2(100, "Device %s reserved=%d for append.\n", rctx.device->hdr.name,
664 rctx.jcr->dcr->dev->reserved_device);
666 Dmsg2(100, "Device %s reserved=%d for read.\n", rctx.device->hdr.name,
667 rctx.jcr->read_dcr->dev->reserved_device);
669 if (rctx.notify_dir) {
670 pm_strcpy(dev_name, rctx.device->hdr.name);
671 bash_spaces(dev_name);
672 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
673 Dmsg1(100, ">dird changer: %s", dir->msg);
682 /* Now if requested look through regular devices */
683 if (!rctx.autochanger_only) {
684 foreach_res(rctx.device, R_DEVICE) {
685 Dmsg1(150, "Try match res=%s\n", rctx.device->hdr.name);
686 /* Find resource, and make sure we were able to open it */
687 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
688 stat = reserve_device(rctx);
692 if (rctx.notify_dir) {
693 bash_spaces(rctx.device_name);
694 ok = bnet_fsend(dir, OK_device, rctx.device_name);
695 Dmsg1(100, ">dird dev: %s", dir->msg);
703 return -1; /* nothing found */
707 * Try to reserve a specific device.
709 * Returns: 1 -- OK, have DCR
713 static int reserve_device(RCTX &rctx)
717 const int name_len = MAX_NAME_LENGTH;
719 /* Make sure MediaType is OK */
720 Dmsg2(110, "MediaType device=%s request=%s\n",
721 rctx.device->media_type, rctx.store->media_type);
722 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
726 /* Make sure device exists -- i.e. we can stat() it */
727 if (!rctx.device->dev) {
728 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
730 if (!rctx.device->dev) {
731 if (rctx.device->changer_res) {
732 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
733 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
734 rctx.device->hdr.name, rctx.device_name);
736 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
737 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
740 return -1; /* no use waiting */
743 rctx.suitable_device = true;
744 Dmsg2(110, "Try reserve %s JobId=%u\n", rctx.device->hdr.name,
746 dcr = new_dcr(rctx.jcr, rctx.device->dev);
748 BSOCK *dir = rctx.jcr->dir_bsock;
749 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
750 Dmsg1(100, ">dird: %s", dir->msg);
753 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
754 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
755 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
756 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
757 if (rctx.store->append == SD_APPEND) {
758 if (rctx.exact_match && !rctx.have_volume) {
759 dcr->any_volume = true;
760 if (dir_find_next_appendable_volume(dcr)) {
761 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
762 Dmsg2(100, "JobId=%u looking for Volume=%s\n", rctx.jcr->JobId, rctx.VolumeName);
763 rctx.have_volume = true;
765 Dmsg0(100, "No next volume found\n");
766 rctx.VolumeName[0] = 0;
769 ok = reserve_device_for_append(dcr, rctx);
772 Dmsg5(100, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
773 dcr->dev->reserved_device,
774 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
777 ok = reserve_device_for_read(dcr);
779 rctx.jcr->read_dcr = dcr;
780 Dmsg5(100, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
781 dcr->dev->reserved_device,
782 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
787 Dmsg0(110, "Not OK.\n");
794 * We "reserve" the drive by setting the ST_READ bit. No one else
795 * should touch the drive until that is cleared.
796 * This allows the DIR to "reserve" the device before actually
799 static bool reserve_device_for_read(DCR *dcr)
801 DEVICE *dev = dcr->dev;
807 /* Get locks in correct order */
808 unlock_reservations();
812 if (is_device_unmounted(dev)) {
813 Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
814 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
815 jcr->JobId, dev->print_name());
816 queue_reserve_message(jcr);
820 if (dev->is_busy()) {
821 Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
822 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
823 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
824 jcr->JobId, dev->print_name());
825 queue_reserve_message(jcr);
832 dev->reserved_device++;
833 Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
834 dev->print_name(), dev);
835 dcr->reserved_device = true;
844 * We reserve the device for appending by incrementing the
845 * reserved_device. We do virtually all the same work that
846 * is done in acquire_device_for_append(), but we do
847 * not attempt to mount the device. This routine allows
848 * the DIR to reserve multiple devices before *really*
849 * starting the job. It also permits the SD to refuse
850 * certain devices (not up, ...).
852 * Note, in reserving a device, if the device is for the
853 * same pool and the same pool type, then it is acceptable.
854 * The Media Type has already been checked. If we are
855 * the first tor reserve the device, we put the pool
856 * name and pool type in the device record.
858 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
861 DEVICE *dev = dcr->dev;
866 /* Get locks in correct order */
867 unlock_reservations();
871 /* If device is being read, we cannot write it */
872 if (dev->can_read()) {
873 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
874 jcr->JobId, dev->print_name());
875 Dmsg1(110, "%s", jcr->errmsg);
876 queue_reserve_message(jcr);
880 /* If device is unmounted, we are out of luck */
881 if (is_device_unmounted(dev)) {
882 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
883 jcr->JobId, dev->print_name());
884 Dmsg1(110, "%s", jcr->errmsg);
885 queue_reserve_message(jcr);
889 Dmsg1(110, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
891 /* Now do detailed tests ... */
892 if (can_reserve_drive(dcr, rctx) != 1) {
893 Dmsg0(110, "can_reserve_drive!=1\n");
897 dev->reserved_device++;
898 Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
899 dev->print_name(), dev);
900 dcr->reserved_device = true;
909 * Returns: 1 if drive can be reserved
910 * 0 if we should wait
911 * -1 on error or impossibility
913 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
915 DEVICE *dev = dcr->dev;
918 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
919 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
920 rctx.autochanger_only, rctx.any_drive);
922 /* setting any_drive overrides PreferMountedVols flag */
923 if (!rctx.any_drive) {
925 * When PreferMountedVols is set, we keep track of the
926 * drive in use that has the least number of writers, then if
927 * no unmounted drive is found, we try that drive. This
928 * helps spread the load to the least used drives.
930 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
931 Dmsg3(110, "OK dev=%s == low_drive=%s. JobId=%u\n",
932 dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
935 /* If he wants a free drive, but this one is busy, no go */
936 if (!rctx.PreferMountedVols && dev->is_busy()) {
937 /* Save least used drive */
938 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
939 rctx.num_writers = dev->num_writers + dev->reserved_device;
940 rctx.low_use_drive = dev;
941 Dmsg2(110, "set low use drive=%s num_writers=%d\n", dev->print_name(),
944 Dmsg1(110, "not low use num_writers=%d\n", dev->num_writers+
945 dev->reserved_device);
947 Dmsg1(110, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
948 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
949 jcr->JobId, dev->print_name());
950 queue_reserve_message(jcr);
954 /* Check for prefer mounted volumes */
955 if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
956 Mmsg(jcr->errmsg, _("3606 JobId=%u prefers mounted drives, but drive %s has no Volume.\n"),
957 jcr->JobId, dev->print_name());
958 queue_reserve_message(jcr);
959 Dmsg1(110, "failed: want mounted -- no vol JobId=%u\n", jcr->JobId);
960 return 0; /* No volume mounted */
963 /* Check for exact Volume name match */
964 if (rctx.exact_match && rctx.have_volume &&
965 strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
966 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
967 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
969 queue_reserve_message(jcr);
970 Dmsg2(110, "failed: Not exact match have=%s want=%s\n",
971 dev->VolHdr.VolumeName, rctx.VolumeName);
976 /* Check for unused autochanger drive */
977 if (rctx.autochanger_only && dev->num_writers == 0 &&
978 dev->VolHdr.VolumeName[0] == 0) {
979 /* Device is available but not yet reserved, reserve it for us */
980 Dmsg2(100, "OK Res Unused autochanger %s JobId=%u.\n",
981 dev->print_name(), jcr->JobId);
982 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
983 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
984 return 1; /* reserve drive */
988 * Handle the case that there are no writers
990 if (dev->num_writers == 0) {
991 /* Now check if there are any reservations on the drive */
992 if (dev->reserved_device) {
993 /* Now check if we want the same Pool and pool type */
994 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
995 strcmp(dev->pool_type, dcr->pool_type) == 0) {
996 /* OK, compatible device */
997 Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
998 dev->print_name(), jcr->JobId);
1001 /* Drive Pool not suitable for us */
1002 Mmsg(jcr->errmsg, _(
1003 "3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"),
1004 jcr->JobId, dcr->pool_name, dev->pool_name,
1005 dev->reserved_device, dev->print_name());
1006 queue_reserve_message(jcr);
1007 Dmsg2(110, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
1008 dev->pool_name, dcr->pool_name);
1009 return 0; /* wait */
1011 } else if (dev->can_append()) {
1012 /* Device in append mode, check if changing pool */
1013 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1014 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1015 Dmsg2(100, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
1016 dev->print_name(), jcr->JobId);
1017 /* OK, compatible device */
1020 /* Changing pool, unload old tape if any in drive */
1021 Dmsg0(100, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
1022 unload_autochanger(dcr, 0);
1025 /* Device is available but not yet reserved, reserve it for us */
1026 Dmsg2(100, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
1028 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1029 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1030 return 1; /* reserve drive */
1034 * Check if the device is in append mode with writers (i.e.
1035 * available if pool is the same).
1037 if (dev->can_append() || dev->num_writers > 0) {
1038 /* Yes, now check if we want the same Pool and pool type */
1039 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1040 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1041 Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
1042 dev->print_name(), jcr->JobId);
1043 /* OK, compatible device */
1046 /* Drive Pool not suitable for us */
1047 Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but has Pool=\"%s\" on drive %s.\n"),
1048 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
1049 queue_reserve_message(jcr);
1050 Dmsg2(110, "failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
1051 dev->pool_name, dcr->pool_name);
1052 return 0; /* wait */
1055 Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
1056 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
1057 jcr->JobId, dev->print_name());
1058 queue_reserve_message(jcr);
1059 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
1060 return -1; /* error, should not get here */
1062 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
1063 jcr->JobId, dev->print_name());
1064 queue_reserve_message(jcr);
1065 Dmsg2(110, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
1070 * search_lock is already set on entering this routine
1072 static void queue_reserve_message(JCR *jcr)
1075 alist *msgs = jcr->reserve_msgs;
1082 * Look for duplicate message. If found, do
1085 for (i=msgs->size()-1; i >= 0; i--) {
1086 msg = (char *)msgs->get(i);
1090 /* Comparison based on 4 digit message number */
1091 if (strncmp(msg, jcr->errmsg, 4) == 0) {
1095 /* Message unique, so insert it */
1096 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1100 * Send any reservation messages queued for this jcr
1102 void send_drive_reserve_messages(JCR *jcr, void sendit(const char *msg, int len, void *sarg), void *arg)
1108 lock_reservations();
1109 msgs = jcr->reserve_msgs;
1110 if (!msgs || msgs->size() == 0) {
1111 unlock_reservations();
1114 for (i=msgs->size()-1; i >= 0; i--) {
1115 msg = (char *)msgs->get(i);
1117 sendit(" ", 3, arg);
1118 sendit(msg, strlen(msg), arg);
1123 unlock_reservations();