2 * Drive reservation functions for Storage Daemon
6 * Split from job.c and acquire.c June 2005
12 Copyright (C) 2000-2006 Kern Sibbald
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License
16 version 2 as amended with additional clauses defined in the
17 file LICENSE in the main source directory.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 the file LICENSE for additional details.
29 static dlist *vol_list = NULL;
30 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
32 /* Forward referenced functions */
33 static int can_reserve_drive(DCR *dcr, RCTX &rctx);
34 static int reserve_device(RCTX &rctx);
35 static bool reserve_device_for_read(DCR *dcr);
36 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
37 static bool use_storage_cmd(JCR *jcr);
38 static void queue_reserve_message(JCR *jcr);
40 /* Requests from the Director daemon */
41 static char use_storage[] = "use storage=%127s media_type=%127s "
42 "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
43 static char use_device[] = "use device=%127s\n";
45 /* Responses sent to Director daemon */
46 static char OK_device[] = "3000 OK use device device=%s\n";
47 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
48 static char BAD_use[] = "3913 Bad use command: %s\n";
50 bool use_cmd(JCR *jcr)
53 * Get the device, media, and pool information
55 if (!use_storage_cmd(jcr)) {
56 set_jcr_job_status(jcr, JS_ErrorTerminated);
57 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
63 static int my_compare(void *item1, void *item2)
65 return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
68 static brwlock_t reservation_lock;
70 void init_reservations_lock()
73 if ((errstat=rwl_init(&reservation_lock)) != 0) {
75 Emsg1(M_ABORT, 0, _("Unable to initialize reservation lock. ERR=%s\n"),
76 be.strerror(errstat));
81 void term_reservations_lock()
83 rwl_destroy(&reservation_lock);
86 /* This applies to a drive and to Volumes */
87 void lock_reservations()
90 if ((errstat=rwl_writelock(&reservation_lock)) != 0) {
92 Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
93 errstat, be.strerror(errstat));
97 void unlock_reservations()
100 if ((errstat=rwl_writeunlock(&reservation_lock)) != 0) {
102 Emsg2(M_ABORT, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
103 errstat, be.strerror(errstat));
109 * Put a new Volume entry in the Volume list. This
110 * effectively reserves the volume so that it will
111 * not be mounted again.
113 * Return: VOLRES entry on success
114 * NULL if the Volume is already in the list
116 VOLRES *new_volume(DCR *dcr, const char *VolumeName)
120 Dmsg1(400, "new_volume %s\n", VolumeName);
122 * We lock the reservations system here to ensure
123 * when adding a new volume that no newly scheduled
124 * job can reserve it.
130 foreach_dlist(vol, vol_list) {
131 if (vol && vol->dev == dcr->dev) {
132 vol_list->remove(vol);
141 vol = (VOLRES *)malloc(sizeof(VOLRES));
142 memset(vol, 0, sizeof(VOLRES));
143 vol->vol_name = bstrdup(VolumeName);
146 Dmsg2(100, "New Vol=%s dev=%s\n", VolumeName, dcr->dev->print_name());
147 nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
153 DEVICE *dev = nvol->dev;
154 if (!dev->is_busy()) {
155 Dmsg3(100, "Swap vol=%s from dev=%s to %s\n", VolumeName,
156 dev->print_name(), dcr->dev->print_name());
157 nvol->dev = dcr->dev;
158 dev->VolHdr.VolumeName[0] = 0;
160 Dmsg3(100, "!!!! could not swap vol=%s from dev=%s to %s\n", VolumeName,
161 dev->print_name(), dcr->dev->print_name());
166 unlock_reservations();
171 * Search for a Volume name in the Volume list.
173 * Returns: VOLRES entry on success
174 * NULL if the Volume is not in the list
176 VOLRES *find_volume(const char *VolumeName)
179 /* Do not lock reservations here */
181 vol.vol_name = bstrdup(VolumeName);
182 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
189 * Free a Volume from the Volume list
191 * Returns: true if the Volume found and removed from the list
192 * false if the Volume is not in the list
194 bool free_volume(DEVICE *dev)
199 if (dev->VolHdr.VolumeName[0] == 0) {
200 Dmsg1(100, "free_volume: no vol on dev %s\n", dev->print_name());
202 * Our device has no VolumeName listed, but
203 * search the list for any Volume attached to
204 * this device and remove it.
206 foreach_dlist(fvol, vol_list) {
207 if (fvol && fvol->dev == dev) {
208 vol_list->remove(fvol);
209 if (fvol->vol_name) {
210 Dmsg2(100, "free_volume %s dev=%s\n", fvol->vol_name, dev->print_name());
211 free(fvol->vol_name);
219 Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
220 vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
221 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
223 vol_list->remove(fvol);
224 Dmsg2(100, "free_volume %s dev=%s\n", fvol->vol_name, dev->print_name());
225 free(fvol->vol_name);
229 dev->VolHdr.VolumeName[0] = 0;
235 /* Free volume reserved by this dcr but not attached to a dev */
236 void free_unused_volume(DCR *dcr)
241 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
242 if (vol->dcr == dcr && (vol->dev == NULL ||
243 strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
244 vol_list->remove(vol);
245 Dmsg1(100, "free_unused_olume %s\n", vol->vol_name);
255 * List Volumes -- this should be moved to status.c
257 void list_volumes(BSOCK *user)
261 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
263 bnet_fsend(user, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
265 bnet_fsend(user, "%s\n", vol->vol_name);
271 /* Create the Volume list */
272 void create_volume_list()
274 VOLRES *dummy = NULL;
275 if (vol_list == NULL) {
276 vol_list = New(dlist(dummy, &dummy->link));
280 /* Release all Volumes from the list */
281 void free_volume_list()
288 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
289 Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
297 bool is_volume_in_use(DCR *dcr)
299 VOLRES *vol = find_volume(dcr->VolumeName);
301 Dmsg1(100, "Vol=%s not in use.\n", dcr->VolumeName);
302 return false; /* vol not in list */
304 if (!vol->dev) { /* vol not attached to device */
305 Dmsg1(100, "Vol=%s has no dev.\n", dcr->VolumeName);
308 if (dcr->dev == vol->dev) { /* same device OK */
309 Dmsg1(100, "Vol=%s on same dev.\n", dcr->VolumeName);
312 if (!vol->dev->is_busy()) {
313 Dmsg2(100, "Vol=%s dev=%s not busy.\n", dcr->VolumeName, vol->dev->print_name());
316 Dmsg2(100, "Vol=%s used by %s.\n", dcr->VolumeName, vol->dev->print_name());
322 * We get the following type of information:
324 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
328 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
332 static bool use_storage_cmd(JCR *jcr)
334 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
335 BSOCK *dir = jcr->dir_bsock;
345 memset(&rctx, 0, sizeof(RCTX));
348 * If there are multiple devices, the director sends us
349 * use_device for each device that it wants to use.
351 dirstore = New(alist(10, not_owned_by_alist));
352 // Dmsg2(000, "dirstore=%p JobId=%u\n", dirstore, jcr->JobId);
353 msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
355 Dmsg1(100, "<dird: %s", dir->msg);
356 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
357 media_type.c_str(), pool_name.c_str(),
358 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
363 jcr->write_store = dirstore;
365 jcr->read_store = dirstore;
367 rctx.append = append;
368 unbash_spaces(store_name);
369 unbash_spaces(media_type);
370 unbash_spaces(pool_name);
371 unbash_spaces(pool_type);
372 store = new DIRSTORE;
373 dirstore->append(store);
374 memset(store, 0, sizeof(DIRSTORE));
375 store->device = New(alist(10));
376 bstrncpy(store->name, store_name, sizeof(store->name));
377 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
378 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
379 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
380 store->append = append;
382 /* Now get all devices */
383 while (bnet_recv(dir) >= 0) {
384 Dmsg1(100, "<dird device: %s", dir->msg);
385 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
389 unbash_spaces(dev_name);
390 store->device->append(bstrdup(dev_name.c_str()));
392 } while (ok && bnet_recv(dir) >= 0);
395 /* This loop is debug code and can be removed */
396 /* ***FIXME**** remove after 1.38 release */
398 foreach_alist(store, dirstore) {
399 Dmsg5(110, "Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n",
400 store->name, store->media_type, store->pool_name,
401 store->pool_type, store->append);
402 foreach_alist(device_name, store->device) {
403 Dmsg1(110, " Device=%s\n", device_name);
408 init_jcr_device_wait_timers(jcr);
410 * At this point, we have a list of all the Director's Storage
411 * resources indicated for this Job, which include Pool, PoolType,
412 * storage name, and Media type.
413 * Then for each of the Storage resources, we have a list of
414 * device names that were given.
416 * Wiffle through them and find one that can do the backup.
419 bool first = true; /* print wait message once */
421 rctx.notify_dir = true;
423 for ( ; !fail && !job_canceled(jcr); ) {
424 while ((msg = (char *)msgs->pop())) {
427 rctx.suitable_device = false;
428 rctx.have_volume = false;
429 rctx.any_drive = false;
430 if (!jcr->PreferMountedVols) {
431 /* Look for unused drives in autochangers */
432 rctx.num_writers = 20000000; /* start with impossible number */
433 rctx.low_use_drive = NULL;
434 rctx.PreferMountedVols = false;
435 rctx.exact_match = false;
436 rctx.autochanger_only = true;
437 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
438 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
439 rctx.autochanger_only, rctx.any_drive);
440 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
443 /* Look through all drives possibly for low_use drive */
444 if (rctx.low_use_drive) {
445 rctx.try_low_use_drive = true;
446 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
449 rctx.try_low_use_drive = false;
451 rctx.autochanger_only = false;
452 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
453 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
454 rctx.autochanger_only, rctx.any_drive);
455 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
459 /* Look for an exact match all drives */
460 rctx.PreferMountedVols = true;
461 rctx.exact_match = true;
462 rctx.autochanger_only = false;
463 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
464 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
465 rctx.autochanger_only, rctx.any_drive);
466 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
469 /* Look for any mounted drive */
470 rctx.exact_match = false;
471 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
472 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
473 rctx.autochanger_only, rctx.any_drive);
474 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
478 rctx.any_drive = true;
479 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
480 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
481 rctx.autochanger_only, rctx.any_drive);
482 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
485 /* Keep reservations locked *except* during wait_for_device() */
486 unlock_reservations();
487 if (!rctx.suitable_device || !wait_for_device(jcr, first)) {
488 Dmsg0(100, "Fail. !suitable_device || !wait_for_device\n");
493 bnet_sig(dir, BNET_HEARTBEAT); /* Inform Dir that we are alive */
495 unlock_reservations();
498 * If we get here, there are no suitable devices available, which
499 * means nothing configured. If a device is suitable but busy
500 * with another Volume, we will not come here.
502 unbash_spaces(dir->msg);
503 pm_strcpy(jcr->errmsg, dir->msg);
504 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
505 Jmsg(jcr, M_FATAL, 0, _("\n"
506 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
507 dev_name.c_str(), media_type.c_str());
508 bnet_fsend(dir, NO_device, dev_name.c_str());
510 Dmsg1(100, ">dird: %s", dir->msg);
513 unbash_spaces(dir->msg);
514 pm_strcpy(jcr->errmsg, dir->msg);
515 Jmsg(jcr, M_FATAL, 0, _("Failed command: %s\n"), jcr->errmsg);
516 bnet_fsend(dir, BAD_use, jcr->errmsg);
517 Dmsg1(100, ">dird: %s", dir->msg);
524 void release_msgs(JCR *jcr)
526 alist *msgs = jcr->reserve_msgs;
533 while ((msg = (char *)msgs->pop())) {
537 jcr->reserve_msgs = NULL;
538 unlock_reservations();
542 * Search for a device suitable for this job.
544 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
552 dirstore = jcr->write_store;
554 dirstore = jcr->read_store;
557 * For each storage device that the user specified, we
558 * search and see if there is a resource for that device.
560 Dmsg4(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
561 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
562 rctx.autochanger_only);
564 foreach_alist(store, dirstore) {
566 foreach_alist(device_name, store->device) {
568 rctx.device_name = device_name;
569 stat = search_res_for_device(rctx);
570 if (stat == 1) { /* found available device */
571 Dmsg1(100, "Suitable device found=%s\n", device_name);
574 } else if (stat == 0) { /* device busy */
575 Dmsg1(110, "Suitable device found=%s, not used: busy\n", device_name);
577 /* otherwise error */
578 Dmsg0(110, "No suitable device found.\n");
590 * Search for a particular storage device with particular storage
591 * characteristics (MediaType).
593 int search_res_for_device(RCTX &rctx)
595 AUTOCHANGER *changer;
596 BSOCK *dir = rctx.jcr->dir_bsock;
600 Dmsg1(110, "Search res for %s\n", rctx.device_name);
601 /* Look through Autochangers first */
602 foreach_res(changer, R_AUTOCHANGER) {
603 Dmsg1(150, "Try match changer res=%s\n", changer->hdr.name);
604 /* Find resource, and make sure we were able to open it */
605 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
606 /* Try each device in this AutoChanger */
607 foreach_alist(rctx.device, changer->device) {
608 Dmsg1(110, "Try changer device %s\n", rctx.device->hdr.name);
609 stat = reserve_device(rctx);
610 if (stat != 1) { /* try another device */
614 if (rctx.store->append == SD_APPEND) {
615 Dmsg2(100, "Device %s reserved=%d for append.\n", rctx.device->hdr.name,
616 rctx.jcr->dcr->dev->reserved_device);
618 Dmsg2(100, "Device %s reserved=%d for read.\n", rctx.device->hdr.name,
619 rctx.jcr->read_dcr->dev->reserved_device);
621 if (rctx.notify_dir) {
622 pm_strcpy(dev_name, rctx.device->hdr.name);
623 bash_spaces(dev_name);
624 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
625 Dmsg1(100, ">dird changer: %s", dir->msg);
634 /* Now if requested look through regular devices */
635 if (!rctx.autochanger_only) {
636 foreach_res(rctx.device, R_DEVICE) {
637 Dmsg1(150, "Try match res=%s\n", rctx.device->hdr.name);
638 /* Find resource, and make sure we were able to open it */
639 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
640 stat = reserve_device(rctx);
644 if (rctx.notify_dir) {
645 bash_spaces(rctx.device_name);
646 ok = bnet_fsend(dir, OK_device, rctx.device_name);
647 Dmsg1(100, ">dird dev: %s", dir->msg);
655 return -1; /* nothing found */
659 * Try to reserve a specific device.
661 * Returns: 1 -- OK, have DCR
665 static int reserve_device(RCTX &rctx)
669 const int name_len = MAX_NAME_LENGTH;
671 /* Make sure MediaType is OK */
672 Dmsg2(110, "MediaType device=%s request=%s\n",
673 rctx.device->media_type, rctx.store->media_type);
674 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
678 /* Make sure device exists -- i.e. we can stat() it */
679 if (!rctx.device->dev) {
680 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
682 if (!rctx.device->dev) {
683 if (rctx.device->changer_res) {
684 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
685 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
686 rctx.device->hdr.name, rctx.device_name);
688 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
689 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
692 return -1; /* no use waiting */
695 rctx.suitable_device = true;
696 Dmsg2(110, "Try reserve %s JobId=%u\n", rctx.device->hdr.name,
698 dcr = new_dcr(rctx.jcr, rctx.device->dev);
700 BSOCK *dir = rctx.jcr->dir_bsock;
701 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
702 Dmsg1(100, ">dird: %s", dir->msg);
705 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
706 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
707 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
708 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
709 if (rctx.store->append == SD_APPEND) {
710 if (rctx.exact_match && !rctx.have_volume) {
711 dcr->any_volume = true;
712 if (dir_find_next_appendable_volume(dcr)) {
713 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
714 Dmsg2(100, "JobId=%u looking for Volume=%s\n", rctx.jcr->JobId, rctx.VolumeName);
715 rctx.have_volume = true;
717 Dmsg0(100, "No next volume found\n");
718 rctx.VolumeName[0] = 0;
721 ok = reserve_device_for_append(dcr, rctx);
724 Dmsg5(100, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
725 dcr->dev->reserved_device,
726 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
729 ok = reserve_device_for_read(dcr);
731 rctx.jcr->read_dcr = dcr;
732 Dmsg5(100, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
733 dcr->dev->reserved_device,
734 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
739 Dmsg0(110, "Not OK.\n");
746 * We "reserve" the drive by setting the ST_READ bit. No one else
747 * should touch the drive until that is cleared.
748 * This allows the DIR to "reserve" the device before actually
751 static bool reserve_device_for_read(DCR *dcr)
753 DEVICE *dev = dcr->dev;
759 /* Get locks in correct order */
760 unlock_reservations();
764 if (is_device_unmounted(dev)) {
765 Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
766 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
767 jcr->JobId, dev->print_name());
768 queue_reserve_message(jcr);
772 if (dev->is_busy()) {
773 Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
774 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
775 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
776 jcr->JobId, dev->print_name());
777 queue_reserve_message(jcr);
784 dev->reserved_device++;
785 Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
786 dev->print_name(), dev);
787 dcr->reserved_device = true;
796 * We reserve the device for appending by incrementing the
797 * reserved_device. We do virtually all the same work that
798 * is done in acquire_device_for_append(), but we do
799 * not attempt to mount the device. This routine allows
800 * the DIR to reserve multiple devices before *really*
801 * starting the job. It also permits the SD to refuse
802 * certain devices (not up, ...).
804 * Note, in reserving a device, if the device is for the
805 * same pool and the same pool type, then it is acceptable.
806 * The Media Type has already been checked. If we are
807 * the first tor reserve the device, we put the pool
808 * name and pool type in the device record.
810 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
813 DEVICE *dev = dcr->dev;
820 /* If device is being read, we cannot write it */
821 if (dev->can_read()) {
822 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
823 jcr->JobId, dev->print_name());
824 Dmsg1(110, "%s", jcr->errmsg);
825 queue_reserve_message(jcr);
829 /* If device is unmounted, we are out of luck */
830 if (is_device_unmounted(dev)) {
831 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
832 jcr->JobId, dev->print_name());
833 Dmsg1(110, "%s", jcr->errmsg);
834 queue_reserve_message(jcr);
838 Dmsg1(110, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
840 /* Now do detailed tests ... */
841 if (can_reserve_drive(dcr, rctx) != 1) {
842 Dmsg0(110, "can_reserve_drive!=1\n");
846 dev->reserved_device++;
847 Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
848 dev->print_name(), dev);
849 dcr->reserved_device = true;
858 * Returns: 1 if drive can be reserved
859 * 0 if we should wait
860 * -1 on error or impossibility
862 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
864 DEVICE *dev = dcr->dev;
867 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
868 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
869 rctx.autochanger_only, rctx.any_drive);
871 /* setting any_drive overrides PreferMountedVols flag */
872 if (!rctx.any_drive) {
874 * When PreferMountedVols is set, we keep track of the
875 * drive in use that has the least number of writers, then if
876 * no unmounted drive is found, we try that drive. This
877 * helps spread the load to the least used drives.
879 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
880 Dmsg3(110, "OK dev=%s == low_drive=%s. JobId=%u\n",
881 dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
884 /* If he wants a free drive, but this one is busy, no go */
885 if (!rctx.PreferMountedVols && dev->is_busy()) {
886 /* Save least used drive */
887 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
888 rctx.num_writers = dev->num_writers + dev->reserved_device;
889 rctx.low_use_drive = dev;
890 Dmsg2(110, "set low use drive=%s num_writers=%d\n", dev->print_name(),
893 Dmsg1(110, "not low use num_writers=%d\n", dev->num_writers+
894 dev->reserved_device);
896 Dmsg1(110, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
897 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
898 jcr->JobId, dev->print_name());
899 queue_reserve_message(jcr);
903 /* Check for prefer mounted volumes */
904 if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
905 Mmsg(jcr->errmsg, _("3606 JobId=%u wants mounted, but drive %s has no Volume.\n"),
906 jcr->JobId, dev->print_name());
907 queue_reserve_message(jcr);
908 Dmsg1(110, "failed: want mounted -- no vol JobId=%u\n", jcr->JobId);
909 return 0; /* No volume mounted */
912 /* Check for exact Volume name match */
913 if (rctx.exact_match && rctx.have_volume &&
914 strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
915 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
916 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
918 queue_reserve_message(jcr);
919 Dmsg2(110, "failed: Not exact match have=%s want=%s\n",
920 dev->VolHdr.VolumeName, rctx.VolumeName);
925 /* Check for unused autochanger drive */
926 if (rctx.autochanger_only && dev->num_writers == 0 &&
927 dev->VolHdr.VolumeName[0] == 0) {
928 /* Device is available but not yet reserved, reserve it for us */
929 Dmsg2(100, "OK Res Unused autochanger %s JobId=%u.\n",
930 dev->print_name(), jcr->JobId);
931 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
932 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
933 return 1; /* reserve drive */
937 * Handle the case that there are no writers
939 if (dev->num_writers == 0) {
940 /* Now check if there are any reservations on the drive */
941 if (dev->reserved_device) {
942 /* Now check if we want the same Pool and pool type */
943 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
944 strcmp(dev->pool_type, dcr->pool_type) == 0) {
945 /* OK, compatible device */
946 Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
947 dev->print_name(), jcr->JobId);
950 /* Drive Pool not suitable for us */
951 Mmsg(jcr->errmsg, _("3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"),
952 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
953 queue_reserve_message(jcr);
954 Dmsg2(110, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
955 dev->pool_name, dcr->pool_name);
958 } else if (dev->can_append()) {
959 /* Device in append mode, check if changing pool */
960 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
961 strcmp(dev->pool_type, dcr->pool_type) == 0) {
962 Dmsg2(100, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
963 dev->print_name(), jcr->JobId);
964 /* OK, compatible device */
967 /* Changing pool, unload old tape if any in drive */
968 Dmsg0(100, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
969 unload_autochanger(dcr, 0);
972 /* Device is available but not yet reserved, reserve it for us */
973 Dmsg2(100, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
975 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
976 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
977 return 1; /* reserve drive */
981 * Check if the device is in append mode with writers (i.e.
982 * available if pool is the same).
984 if (dev->can_append() || dev->num_writers > 0) {
985 /* Yes, now check if we want the same Pool and pool type */
986 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
987 strcmp(dev->pool_type, dcr->pool_type) == 0) {
988 Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
989 dev->print_name(), jcr->JobId);
990 /* OK, compatible device */
993 /* Drive Pool not suitable for us */
994 Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"),
995 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
996 queue_reserve_message(jcr);
997 Dmsg2(110, "failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
998 dev->pool_name, dcr->pool_name);
1002 Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
1003 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
1004 jcr->JobId, dev->print_name());
1005 queue_reserve_message(jcr);
1006 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
1007 return -1; /* error, should not get here */
1009 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
1010 jcr->JobId, dev->print_name());
1011 queue_reserve_message(jcr);
1012 Dmsg2(110, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
1017 * search_lock is already set on entering this routine
1019 static void queue_reserve_message(JCR *jcr)
1022 alist *msgs = jcr->reserve_msgs;
1029 * Look for duplicate message. If found, do
1032 for (i=msgs->size()-1; i >= 0; i--) {
1033 msg = (char *)msgs->get(i);
1037 /* Comparison based on 4 digit message number */
1038 if (strncmp(msg, jcr->errmsg, 4) == 0) {
1042 /* Message unique, so insert it */
1043 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1047 * Send any reservation messages queued for this jcr
1049 void send_drive_reserve_messages(JCR *jcr, BSOCK *user)
1055 lock_reservations();
1056 msgs = jcr->reserve_msgs;
1057 if (!msgs || msgs->size() == 0) {
1058 unlock_reservations();
1061 for (i=msgs->size()-1; i >= 0; i--) {
1062 msg = (char *)msgs->get(i);
1064 bnet_fsend(user, " %s", msg);
1069 unlock_reservations();