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;
344 memset(&rctx, 0, sizeof(RCTX));
347 * If there are multiple devices, the director sends us
348 * use_device for each device that it wants to use.
350 jcr->dirstore = New(alist(10, not_owned_by_alist));
351 msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
353 Dmsg1(100, "<dird: %s", dir->msg);
354 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
355 media_type.c_str(), pool_name.c_str(),
356 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
360 unbash_spaces(store_name);
361 unbash_spaces(media_type);
362 unbash_spaces(pool_name);
363 unbash_spaces(pool_type);
364 store = new DIRSTORE;
365 jcr->dirstore->append(store);
366 memset(store, 0, sizeof(DIRSTORE));
367 store->device = New(alist(10));
368 bstrncpy(store->name, store_name, sizeof(store->name));
369 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
370 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
371 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
372 store->append = append;
374 /* Now get all devices */
375 while (bnet_recv(dir) >= 0) {
376 Dmsg1(100, "<dird device: %s", dir->msg);
377 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
381 unbash_spaces(dev_name);
382 store->device->append(bstrdup(dev_name.c_str()));
384 } while (ok && bnet_recv(dir) >= 0);
387 /* This loop is debug code and can be removed */
388 /* ***FIXME**** remove after 1.38 release */
390 foreach_alist(store, jcr->dirstore) {
391 Dmsg5(110, "Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n",
392 store->name, store->media_type, store->pool_name,
393 store->pool_type, store->append);
394 foreach_alist(device_name, store->device) {
395 Dmsg1(110, " Device=%s\n", device_name);
400 init_jcr_device_wait_timers(jcr);
402 * At this point, we have a list of all the Director's Storage
403 * resources indicated for this Job, which include Pool, PoolType,
404 * storage name, and Media type.
405 * Then for each of the Storage resources, we have a list of
406 * device names that were given.
408 * Wiffle through them and find one that can do the backup.
411 bool first = true; /* print wait message once */
412 rctx.notify_dir = true;
413 for ( ; !job_canceled(jcr); ) {
414 lock_reservations(); /* only one thread at a time */
415 while ((msg = (char *)msgs->pop())) {
418 rctx.suitable_device = false;
419 rctx.have_volume = false;
420 rctx.any_drive = false;
421 if (!jcr->PreferMountedVols) {
422 /* Look for unused drives in autochangers */
423 rctx.num_writers = 20000000; /* start with impossible number */
424 rctx.low_use_drive = NULL;
425 rctx.PreferMountedVols = false;
426 rctx.exact_match = false;
427 rctx.autochanger_only = true;
428 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
429 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
430 rctx.autochanger_only, rctx.any_drive);
431 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
434 /* Look through all drives possibly for low_use drive */
435 if (rctx.low_use_drive) {
436 rctx.try_low_use_drive = true;
437 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
440 rctx.try_low_use_drive = false;
442 rctx.autochanger_only = false;
443 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
444 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
445 rctx.autochanger_only, rctx.any_drive);
446 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
450 /* Look for an exact match all drives */
451 rctx.PreferMountedVols = true;
452 rctx.exact_match = true;
453 rctx.autochanger_only = false;
454 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
455 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
456 rctx.autochanger_only, rctx.any_drive);
457 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
460 /* Look for any mounted drive */
461 rctx.exact_match = false;
462 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
463 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
464 rctx.autochanger_only, rctx.any_drive);
465 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
469 rctx.any_drive = true;
470 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
471 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
472 rctx.autochanger_only, rctx.any_drive);
473 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
476 /* Unlock before possible wait */
477 unlock_reservations();
478 if (!rctx.suitable_device || !wait_for_device(jcr, first)) {
479 Dmsg0(100, "Fail. !suitable_device || !wait_for_device\n");
480 break; /* Get out, failure ... */
483 bnet_sig(dir, BNET_HEARTBEAT); /* Inform Dir that we are alive */
485 /* Note if !ok then search_lock is already cleared */
487 unlock_reservations();
492 * If we get here, there are no suitable devices available, which
493 * means nothing configured. If a device is suitable but busy
494 * with another Volume, we will not come here.
497 unbash_spaces(dir->msg);
498 pm_strcpy(jcr->errmsg, dir->msg);
499 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
501 Jmsg(jcr, M_FATAL, 0, _("\n"
502 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
503 dev_name.c_str(), media_type.c_str());
504 bnet_fsend(dir, NO_device, dev_name.c_str());
506 Dmsg1(100, ">dird: %s", dir->msg);
508 unbash_spaces(dir->msg);
509 pm_strcpy(jcr->errmsg, dir->msg);
511 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
513 bnet_fsend(dir, BAD_use, jcr->errmsg);
514 Dmsg1(100, ">dird: %s", dir->msg);
522 void release_msgs(JCR *jcr)
524 alist *msgs = jcr->reserve_msgs;
531 while ((msg = (char *)msgs->pop())) {
535 jcr->reserve_msgs = NULL;
536 unlock_reservations();
540 * Search for a device suitable for this job.
542 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
549 * For each storage device that the user specified, we
550 * search and see if there is a resource for that device.
552 Dmsg4(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
553 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
554 rctx.autochanger_only);
556 foreach_alist(store, jcr->dirstore) {
558 foreach_alist(device_name, store->device) {
560 rctx.device_name = device_name;
561 stat = search_res_for_device(rctx);
562 if (stat == 1) { /* found available device */
563 Dmsg1(100, "Suitable device found=%s\n", device_name);
566 } else if (stat == 0) { /* device busy */
567 Dmsg1(110, "Suitable device found=%s, not used: busy\n", device_name);
569 /* otherwise error */
570 Dmsg0(110, "No suitable device found.\n");
582 * Search for a particular storage device with particular storage
583 * characteristics (MediaType).
585 int search_res_for_device(RCTX &rctx)
587 AUTOCHANGER *changer;
588 BSOCK *dir = rctx.jcr->dir_bsock;
592 Dmsg1(110, "Search res for %s\n", rctx.device_name);
593 /* Look through Autochangers first */
594 foreach_res(changer, R_AUTOCHANGER) {
595 Dmsg1(150, "Try match changer res=%s\n", changer->hdr.name);
596 /* Find resource, and make sure we were able to open it */
597 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
598 /* Try each device in this AutoChanger */
599 foreach_alist(rctx.device, changer->device) {
600 Dmsg1(110, "Try changer device %s\n", rctx.device->hdr.name);
601 stat = reserve_device(rctx);
602 if (stat != 1) { /* try another device */
606 if (rctx.store->append == SD_APPEND) {
607 Dmsg2(100, "Device %s reserved=%d for append.\n", rctx.device->hdr.name,
608 rctx.jcr->dcr->dev->reserved_device);
610 Dmsg2(100, "Device %s reserved=%d for read.\n", rctx.device->hdr.name,
611 rctx.jcr->read_dcr->dev->reserved_device);
613 if (rctx.notify_dir) {
614 pm_strcpy(dev_name, rctx.device->hdr.name);
615 bash_spaces(dev_name);
616 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
617 Dmsg1(100, ">dird changer: %s", dir->msg);
626 /* Now if requested look through regular devices */
627 if (!rctx.autochanger_only) {
628 foreach_res(rctx.device, R_DEVICE) {
629 Dmsg1(150, "Try match res=%s\n", rctx.device->hdr.name);
630 /* Find resource, and make sure we were able to open it */
631 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
632 stat = reserve_device(rctx);
636 if (rctx.notify_dir) {
637 bash_spaces(rctx.device_name);
638 ok = bnet_fsend(dir, OK_device, rctx.device_name);
639 Dmsg1(100, ">dird dev: %s", dir->msg);
647 return -1; /* nothing found */
651 * Try to reserve a specific device.
653 * Returns: 1 -- OK, have DCR
657 static int reserve_device(RCTX &rctx)
661 const int name_len = MAX_NAME_LENGTH;
663 /* Make sure MediaType is OK */
664 Dmsg2(110, "MediaType device=%s request=%s\n",
665 rctx.device->media_type, rctx.store->media_type);
666 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
670 /* Make sure device exists -- i.e. we can stat() it */
671 if (!rctx.device->dev) {
672 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
674 if (!rctx.device->dev) {
675 if (rctx.device->changer_res) {
676 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
677 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
678 rctx.device->hdr.name, rctx.device_name);
680 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
681 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
684 return -1; /* no use waiting */
687 rctx.suitable_device = true;
688 Dmsg2(110, "Try reserve %s JobId=%u\n", rctx.device->hdr.name,
690 dcr = new_dcr(rctx.jcr, rctx.device->dev);
692 BSOCK *dir = rctx.jcr->dir_bsock;
693 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
694 Dmsg1(100, ">dird: %s", dir->msg);
697 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
698 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
699 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
700 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
701 if (rctx.store->append == SD_APPEND) {
702 if (rctx.exact_match && !rctx.have_volume) {
703 dcr->any_volume = true;
704 if (dir_find_next_appendable_volume(dcr)) {
705 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
706 Dmsg2(100, "JobId=%u looking for Volume=%s\n", rctx.jcr->JobId, rctx.VolumeName);
707 rctx.have_volume = true;
709 Dmsg0(100, "No next volume found\n");
710 rctx.VolumeName[0] = 0;
713 ok = reserve_device_for_append(dcr, rctx);
716 Dmsg5(100, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
717 dcr->dev->reserved_device,
718 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
721 ok = reserve_device_for_read(dcr);
723 rctx.jcr->read_dcr = dcr;
724 Dmsg5(100, "Read 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);
731 Dmsg0(110, "Not OK.\n");
738 * We "reserve" the drive by setting the ST_READ bit. No one else
739 * should touch the drive until that is cleared.
740 * This allows the DIR to "reserve" the device before actually
743 static bool reserve_device_for_read(DCR *dcr)
745 DEVICE *dev = dcr->dev;
753 if (is_device_unmounted(dev)) {
754 Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
755 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
756 jcr->JobId, dev->print_name());
757 queue_reserve_message(jcr);
761 if (dev->is_busy()) {
762 Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
763 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
764 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
765 jcr->JobId, dev->print_name());
766 queue_reserve_message(jcr);
773 dev->reserved_device++;
774 Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
775 dev->print_name(), dev);
776 dcr->reserved_device = true;
785 * We reserve the device for appending by incrementing the
786 * reserved_device. We do virtually all the same work that
787 * is done in acquire_device_for_append(), but we do
788 * not attempt to mount the device. This routine allows
789 * the DIR to reserve multiple devices before *really*
790 * starting the job. It also permits the SD to refuse
791 * certain devices (not up, ...).
793 * Note, in reserving a device, if the device is for the
794 * same pool and the same pool type, then it is acceptable.
795 * The Media Type has already been checked. If we are
796 * the first tor reserve the device, we put the pool
797 * name and pool type in the device record.
799 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
802 DEVICE *dev = dcr->dev;
809 /* If device is being read, we cannot write it */
810 if (dev->can_read()) {
811 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
812 jcr->JobId, dev->print_name());
813 Dmsg1(110, "%s", jcr->errmsg);
814 queue_reserve_message(jcr);
818 /* If device is unmounted, we are out of luck */
819 if (is_device_unmounted(dev)) {
820 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
821 jcr->JobId, dev->print_name());
822 Dmsg1(110, "%s", jcr->errmsg);
823 queue_reserve_message(jcr);
827 Dmsg1(110, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
829 /* Now do detailed tests ... */
830 if (can_reserve_drive(dcr, rctx) != 1) {
831 Dmsg0(110, "can_reserve_drive!=1\n");
835 dev->reserved_device++;
836 Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
837 dev->print_name(), dev);
838 dcr->reserved_device = true;
847 * Returns: 1 if drive can be reserved
848 * 0 if we should wait
849 * -1 on error or impossibility
851 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
853 DEVICE *dev = dcr->dev;
856 Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
857 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
858 rctx.autochanger_only, rctx.any_drive);
860 /* setting any_drive overrides PreferMountedVols flag */
861 if (!rctx.any_drive) {
863 * When PreferMountedVols is set, we keep track of the
864 * drive in use that has the least number of writers, then if
865 * no unmounted drive is found, we try that drive. This
866 * helps spread the load to the least used drives.
868 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
869 Dmsg3(110, "OK dev=%s == low_drive=%s. JobId=%u\n",
870 dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
873 /* If he wants a free drive, but this one is busy, no go */
874 if (!rctx.PreferMountedVols && dev->is_busy()) {
875 /* Save least used drive */
876 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
877 rctx.num_writers = dev->num_writers + dev->reserved_device;
878 rctx.low_use_drive = dev;
879 Dmsg2(110, "set low use drive=%s num_writers=%d\n", dev->print_name(),
882 Dmsg1(110, "not low use num_writers=%d\n", dev->num_writers+
883 dev->reserved_device);
885 Dmsg1(110, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
886 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
887 jcr->JobId, dev->print_name());
888 queue_reserve_message(jcr);
892 /* Check for prefer mounted volumes */
893 if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
894 Mmsg(jcr->errmsg, _("3606 JobId=%u wants mounted, but drive %s has no Volume.\n"),
895 jcr->JobId, dev->print_name());
896 queue_reserve_message(jcr);
897 Dmsg1(110, "failed: want mounted -- no vol JobId=%u\n", jcr->JobId);
898 return 0; /* No volume mounted */
901 /* Check for exact Volume name match */
902 if (rctx.exact_match && rctx.have_volume &&
903 strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
904 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
905 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
907 queue_reserve_message(jcr);
908 Dmsg2(110, "failed: Not exact match have=%s want=%s\n",
909 dev->VolHdr.VolumeName, rctx.VolumeName);
914 /* Check for unused autochanger drive */
915 if (rctx.autochanger_only && dev->num_writers == 0 &&
916 dev->VolHdr.VolumeName[0] == 0) {
917 /* Device is available but not yet reserved, reserve it for us */
918 Dmsg2(100, "OK Res Unused autochanger %s JobId=%u.\n",
919 dev->print_name(), jcr->JobId);
920 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
921 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
922 return 1; /* reserve drive */
926 * Handle the case that there are no writers
928 if (dev->num_writers == 0) {
929 /* Now check if there are any reservations on the drive */
930 if (dev->reserved_device) {
931 /* Now check if we want the same Pool and pool type */
932 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
933 strcmp(dev->pool_type, dcr->pool_type) == 0) {
934 /* OK, compatible device */
935 Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
936 dev->print_name(), jcr->JobId);
939 /* Drive Pool not suitable for us */
940 Mmsg(jcr->errmsg, _("3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"),
941 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
942 queue_reserve_message(jcr);
943 Dmsg2(110, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
944 dev->pool_name, dcr->pool_name);
947 } else if (dev->can_append()) {
948 /* Device in append mode, check if changing pool */
949 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
950 strcmp(dev->pool_type, dcr->pool_type) == 0) {
951 Dmsg2(100, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
952 dev->print_name(), jcr->JobId);
953 /* OK, compatible device */
956 /* Changing pool, unload old tape if any in drive */
957 Dmsg0(100, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
958 unload_autochanger(dcr, 0);
961 /* Device is available but not yet reserved, reserve it for us */
962 Dmsg2(100, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
964 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
965 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
966 return 1; /* reserve drive */
970 * Check if the device is in append mode with writers (i.e.
971 * available if pool is the same).
973 if (dev->can_append() || dev->num_writers > 0) {
974 /* Yes, now check if we want the same Pool and pool type */
975 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
976 strcmp(dev->pool_type, dcr->pool_type) == 0) {
977 Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
978 dev->print_name(), jcr->JobId);
979 /* OK, compatible device */
982 /* Drive Pool not suitable for us */
983 Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"),
984 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
985 queue_reserve_message(jcr);
986 Dmsg2(110, "failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
987 dev->pool_name, dcr->pool_name);
991 Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
992 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
993 jcr->JobId, dev->print_name());
994 queue_reserve_message(jcr);
995 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
996 return -1; /* error, should not get here */
998 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
999 jcr->JobId, dev->print_name());
1000 queue_reserve_message(jcr);
1001 Dmsg2(110, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
1006 * search_lock is already set on entering this routine
1008 static void queue_reserve_message(JCR *jcr)
1011 alist *msgs = jcr->reserve_msgs;
1018 * Look for duplicate message. If found, do
1021 for (i=msgs->size()-1; i >= 0; i--) {
1022 msg = (char *)msgs->get(i);
1026 /* Comparison based on 4 digit message number */
1027 if (strncmp(msg, jcr->errmsg, 4) == 0) {
1031 /* Message unique, so insert it */
1032 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1036 * Send any reservation messages queued for this jcr
1038 void send_drive_reserve_messages(JCR *jcr, BSOCK *user)
1044 lock_reservations();
1045 msgs = jcr->reserve_msgs;
1046 if (!msgs || msgs->size() == 0) {
1047 unlock_reservations();
1050 for (i=msgs->size()-1; i >= 0; i--) {
1051 msg = (char *)msgs->get(i);
1053 bnet_fsend(user, " %s", msg);
1058 unlock_reservations();