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.
30 static dlist *vol_list = NULL;
31 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
32 static pthread_mutex_t search_lock = PTHREAD_MUTEX_INITIALIZER;
34 /* Forward referenced functions */
35 static int can_reserve_drive(DCR *dcr, RCTX &rctx);
36 static int search_res_for_device(RCTX &rctx);
37 static int reserve_device(RCTX &rctx);
38 static bool reserve_device_for_read(DCR *dcr);
39 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
40 static bool use_storage_cmd(JCR *jcr);
41 static void queue_reserve_message(JCR *jcr);
42 static void release_msgs(JCR *jcr);
44 /* Requests from the Director daemon */
45 static char use_storage[] = "use storage=%127s media_type=%127s "
46 "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
47 static char use_device[] = "use device=%127s\n";
49 /* Responses sent to Director daemon */
50 static char OK_device[] = "3000 OK use device device=%s\n";
51 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
52 static char BAD_use[] = "3913 Bad use command: %s\n";
54 bool use_cmd(JCR *jcr)
57 * Get the device, media, and pool information
59 if (!use_storage_cmd(jcr)) {
60 set_jcr_job_status(jcr, JS_ErrorTerminated);
61 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
67 static int my_compare(void *item1, void *item2)
69 return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
74 * Put a new Volume entry in the Volume list. This
75 * effectively reserves the volume so that it will
76 * not be mounted again.
78 * Return: VOLRES entry on success
79 * NULL if the Volume is already in the list
81 VOLRES *new_volume(DCR *dcr, const char *VolumeName)
85 Dmsg1(400, "new_volume %s\n", VolumeName);
89 foreach_dlist(vol, vol_list) {
90 if (vol && vol->dev == dcr->dev) {
91 vol_list->remove(vol);
100 vol = (VOLRES *)malloc(sizeof(VOLRES));
101 memset(vol, 0, sizeof(VOLRES));
102 vol->vol_name = bstrdup(VolumeName);
105 nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
111 nvol->dev = dcr->dev;
119 * Search for a Volume name in the Volume list.
121 * Returns: VOLRES entry on success
122 * NULL if the Volume is not in the list
124 VOLRES *find_volume(const char *VolumeName)
128 vol.vol_name = bstrdup(VolumeName);
129 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
136 * Free a Volume from the Volume list
138 * Returns: true if the Volume found and removed from the list
139 * false if the Volume is not in the list
141 bool free_volume(DEVICE *dev)
146 if (dev->VolHdr.VolumeName[0] == 0) {
148 * Our device has no VolumeName listed, but
149 * search the list for any Volume attached to
150 * this device and remove it.
152 foreach_dlist(fvol, vol_list) {
153 if (fvol && fvol->dev == dev) {
154 vol_list->remove(fvol);
155 if (fvol->vol_name) {
156 free(fvol->vol_name);
164 Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
165 vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
166 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
168 vol_list->remove(fvol);
169 free(fvol->vol_name);
173 dev->VolHdr.VolumeName[0] = 0;
179 /* Free volume reserved by this dcr but not attached to a dev */
180 void free_unused_volume(DCR *dcr)
184 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
185 if (vol->dcr == dcr && (vol->dev == NULL ||
186 strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
187 vol_list->remove(vol);
197 * List Volumes -- this should be moved to status.c
199 void list_volumes(BSOCK *user)
202 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
204 bnet_fsend(user, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
206 bnet_fsend(user, "%s\n", vol->vol_name);
211 /* Create the Volume list */
212 void init_volume_list()
214 VOLRES *dummy = NULL;
215 if (vol_list == NULL) {
216 vol_list = New(dlist(dummy, &dummy->link));
220 /* Release all Volumes from the list */
221 void free_volume_list()
227 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
228 Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
235 bool is_volume_in_use(DCR *dcr)
237 VOLRES *vol = find_volume(dcr->VolumeName);
239 return false; /* vol not in list */
241 if (!vol->dev) { /* vol not attached to device */
244 if (dcr->dev == vol->dev) { /* same device OK */
247 if (!vol->dev->is_busy()) {
255 * We get the following type of information:
257 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
261 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
265 static bool use_storage_cmd(JCR *jcr)
267 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
268 BSOCK *dir = jcr->dir_bsock;
277 memset(&rctx, 0, sizeof(RCTX));
280 * If there are multiple devices, the director sends us
281 * use_device for each device that it wants to use.
283 jcr->dirstore = New(alist(10, not_owned_by_alist));
284 msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
286 Dmsg1(100, "<dird: %s", dir->msg);
287 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
288 media_type.c_str(), pool_name.c_str(),
289 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
293 unbash_spaces(store_name);
294 unbash_spaces(media_type);
295 unbash_spaces(pool_name);
296 unbash_spaces(pool_type);
297 store = new DIRSTORE;
298 jcr->dirstore->append(store);
299 memset(store, 0, sizeof(DIRSTORE));
300 store->device = New(alist(10));
301 bstrncpy(store->name, store_name, sizeof(store->name));
302 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
303 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
304 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
305 store->append = append;
307 /* Now get all devices */
308 while (bnet_recv(dir) >= 0) {
309 Dmsg1(100, "<dird device: %s", dir->msg);
310 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
314 unbash_spaces(dev_name);
315 store->device->append(bstrdup(dev_name.c_str()));
317 } while (ok && bnet_recv(dir) >= 0);
320 /* This loop is debug code and can be removed */
321 /* ***FIXME**** remove after 1.38 release */
323 foreach_alist(store, jcr->dirstore) {
324 Dmsg5(100, "Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n",
325 store->name, store->media_type, store->pool_name,
326 store->pool_type, store->append);
327 foreach_alist(device_name, store->device) {
328 Dmsg1(100, " Device=%s\n", device_name);
333 init_jcr_device_wait_timers(jcr);
335 * At this point, we have a list of all the Director's Storage
336 * resources indicated for this Job, which include Pool, PoolType,
337 * storage name, and Media type.
338 * Then for each of the Storage resources, we have a list of
339 * device names that were given.
341 * Wiffle through them and find one that can do the backup.
344 bool first = true; /* print wait message once */
345 for ( ; !job_canceled(jcr); ) {
346 P(search_lock); /* only one thread at a time */
347 while ((msg = (char *)msgs->pop())) {
350 rctx.suitable_device = false;
351 rctx.have_volume = false;
352 rctx.any_drive = false;
353 if (!jcr->PreferMountedVols) {
354 /* Look for unused drives in autochangers */
355 rctx.num_writers = 20000000; /* start with impossible number */
356 rctx.low_use_drive = NULL;
357 rctx.PreferMountedVols = false;
358 rctx.exact_match = false;
359 rctx.autochanger_only = true;
360 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
361 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
362 rctx.autochanger_only, rctx.any_drive);
363 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
366 /* Look through all drives possibly for low_use drive */
367 if (rctx.low_use_drive) {
368 rctx.try_low_use_drive = true;
369 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
372 rctx.try_low_use_drive = false;
374 rctx.autochanger_only = false;
375 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
376 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
377 rctx.autochanger_only, rctx.any_drive);
378 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
382 /* Look for an exact match all drives */
383 rctx.PreferMountedVols = true;
384 rctx.exact_match = true;
385 rctx.autochanger_only = false;
386 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
387 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
388 rctx.autochanger_only, rctx.any_drive);
389 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
392 /* Look for any mounted drive */
393 rctx.exact_match = false;
394 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
395 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
396 rctx.autochanger_only, rctx.any_drive);
397 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
401 rctx.any_drive = true;
402 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
403 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
404 rctx.autochanger_only, rctx.any_drive);
405 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
408 /* Unlock before possible wait */
410 if (!rctx.suitable_device || !wait_for_device(jcr, first)) {
411 break; /* Get out, failure ... */
414 bnet_sig(dir, BNET_HEARTBEAT); /* Inform Dir that we are alive */
416 /* Note if !ok then search_lock is already cleared */
423 * If we get here, there are no suitable devices available, which
424 * means nothing configured. If a device is suitable but busy
425 * with another Volume, we will not come here.
428 unbash_spaces(dir->msg);
429 pm_strcpy(jcr->errmsg, dir->msg);
430 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
432 Jmsg(jcr, M_FATAL, 0, _("\n"
433 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
434 dev_name.c_str(), media_type.c_str());
435 bnet_fsend(dir, NO_device, dev_name.c_str());
437 Dmsg1(100, ">dird: %s", dir->msg);
439 unbash_spaces(dir->msg);
440 pm_strcpy(jcr->errmsg, dir->msg);
442 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
444 bnet_fsend(dir, BAD_use, jcr->errmsg);
445 Dmsg1(100, ">dird: %s", dir->msg);
453 static void release_msgs(JCR *jcr)
455 alist *msgs = jcr->reserve_msgs;
459 while ((msg = (char *)msgs->pop())) {
463 jcr->reserve_msgs = NULL;
468 * Search for a device suitable for this job.
470 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
477 * For each storage device that the user specified, we
478 * search and see if there is a resource for that device.
480 Dmsg4(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
481 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
482 rctx.autochanger_only);
484 foreach_alist(store, jcr->dirstore) {
486 foreach_alist(device_name, store->device) {
488 rctx.device_name = device_name;
489 stat = search_res_for_device(rctx);
490 if (stat == 1) { /* found available device */
491 Dmsg1(100, "Suitable device found=%s\n", device_name);
494 } else if (stat == 0) { /* device busy */
495 Dmsg1(100, "Suitable device found=%s, not used: busy\n", device_name);
497 /* otherwise error */
498 Dmsg0(100, "No suitable device found.\n");
510 * Search for a particular storage device with particular storage
511 * characteristics (MediaType).
513 static int search_res_for_device(RCTX &rctx)
515 AUTOCHANGER *changer;
516 BSOCK *dir = rctx.jcr->dir_bsock;
520 Dmsg1(100, "Search res for %s\n", rctx.device_name);
521 /* Look through Autochangers first */
522 foreach_res(changer, R_AUTOCHANGER) {
523 Dmsg1(150, "Try match changer res=%s\n", changer->hdr.name);
524 /* Find resource, and make sure we were able to open it */
525 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
526 /* Try each device in this AutoChanger */
527 foreach_alist(rctx.device, changer->device) {
528 Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
529 stat = reserve_device(rctx);
530 if (stat != 1) { /* try another device */
534 if (rctx.store->append == SD_APPEND) {
535 Dmsg2(100, "Device %s reserved=%d for append.\n", rctx.device->hdr.name,
536 rctx.jcr->dcr->dev->reserved_device);
538 Dmsg2(100, "Device %s reserved=%d for read.\n", rctx.device->hdr.name,
539 rctx.jcr->read_dcr->dev->reserved_device);
541 pm_strcpy(dev_name, rctx.device->hdr.name);
542 bash_spaces(dev_name);
543 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
544 Dmsg1(100, ">dird changer: %s", dir->msg);
550 /* Now if requested look through regular devices */
551 if (!rctx.autochanger_only) {
552 foreach_res(rctx.device, R_DEVICE) {
553 Dmsg1(150, "Try match res=%s\n", rctx.device->hdr.name);
554 /* Find resource, and make sure we were able to open it */
555 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
556 stat = reserve_device(rctx);
560 Dmsg1(220, "Got: %s", dir->msg);
561 bash_spaces(rctx.device_name);
562 ok = bnet_fsend(dir, OK_device, rctx.device_name);
563 Dmsg1(100, ">dird dev: %s", dir->msg);
568 return -1; /* nothing found */
572 * Try to reserve a specific device.
574 * Returns: 1 -- OK, have DCR
578 static int reserve_device(RCTX &rctx)
582 const int name_len = MAX_NAME_LENGTH;
584 /* Make sure MediaType is OK */
585 Dmsg2(100, "MediaType device=%s request=%s\n",
586 rctx.device->media_type, rctx.store->media_type);
587 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
591 /* Make sure device exists -- i.e. we can stat() it */
592 if (!rctx.device->dev) {
593 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
595 if (!rctx.device->dev) {
596 if (rctx.device->changer_res) {
597 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
598 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
599 rctx.device->hdr.name, rctx.device_name);
601 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
602 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
605 return -1; /* no use waiting */
608 rctx.suitable_device = true;
609 Dmsg2(100, "Try reserve %s JobId=%u\n", rctx.device->hdr.name,
611 dcr = new_dcr(rctx.jcr, rctx.device->dev);
613 BSOCK *dir = rctx.jcr->dir_bsock;
614 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
615 Dmsg1(100, ">dird: %s", dir->msg);
618 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
619 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
620 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
621 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
622 if (rctx.store->append == SD_APPEND) {
623 if (rctx.exact_match && !rctx.have_volume) {
624 dcr->any_volume = true;
625 if (dir_find_next_appendable_volume(dcr)) {
626 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
627 Dmsg2(100, "JobId=%u looking for Volume=%s\n", rctx.jcr->JobId, rctx.VolumeName);
628 rctx.have_volume = true;
630 Dmsg0(100, "No next volume found\n");
631 rctx.VolumeName[0] = 0;
634 ok = reserve_device_for_append(dcr, rctx);
637 Dmsg5(100, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
638 dcr->dev->reserved_device,
639 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
642 ok = reserve_device_for_read(dcr);
644 rctx.jcr->read_dcr = dcr;
645 Dmsg5(100, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
646 dcr->dev->reserved_device,
647 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
652 Dmsg0(100, "Not OK.\n");
659 * We "reserve" the drive by setting the ST_READ bit. No one else
660 * should touch the drive until that is cleared.
661 * This allows the DIR to "reserve" the device before actually
664 static bool reserve_device_for_read(DCR *dcr)
666 DEVICE *dev = dcr->dev;
674 if (is_device_unmounted(dev)) {
675 Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
676 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
677 jcr->JobId, dev->print_name());
678 queue_reserve_message(jcr);
682 if (dev->is_busy()) {
683 Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
684 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
685 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
686 jcr->JobId, dev->print_name());
687 queue_reserve_message(jcr);
694 dev->reserved_device++;
695 Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
696 dev->print_name(), dev);
697 dcr->reserved_device = true;
706 * We reserve the device for appending by incrementing the
707 * reserved_device. We do virtually all the same work that
708 * is done in acquire_device_for_append(), but we do
709 * not attempt to mount the device. This routine allows
710 * the DIR to reserve multiple devices before *really*
711 * starting the job. It also permits the SD to refuse
712 * certain devices (not up, ...).
714 * Note, in reserving a device, if the device is for the
715 * same pool and the same pool type, then it is acceptable.
716 * The Media Type has already been checked. If we are
717 * the first tor reserve the device, we put the pool
718 * name and pool type in the device record.
720 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
723 DEVICE *dev = dcr->dev;
730 /* If device is being read, we cannot write it */
731 if (dev->can_read()) {
732 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
733 jcr->JobId, dev->print_name());
734 Dmsg1(100, "%s", jcr->errmsg);
735 queue_reserve_message(jcr);
739 /* If device is unmounted, we are out of luck */
740 if (is_device_unmounted(dev)) {
741 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
742 jcr->JobId, dev->print_name());
743 Dmsg1(100, "%s", jcr->errmsg);
744 queue_reserve_message(jcr);
748 Dmsg1(100, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
750 /* Now do detailed tests ... */
751 if (can_reserve_drive(dcr, rctx) != 1) {
752 Dmsg0(100, "can_reserve_drive!=1\n");
756 dev->reserved_device++;
757 Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
758 dev->print_name(), dev);
759 dcr->reserved_device = true;
768 * Returns: 1 if drive can be reserved
769 * 0 if we should wait
770 * -1 on error or impossibility
772 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
774 DEVICE *dev = dcr->dev;
777 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
778 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
779 rctx.autochanger_only, rctx.any_drive);
781 /* setting any_drive overrides PreferMountedVols flag */
782 if (!rctx.any_drive) {
784 * When PreferMountedVols is set, we keep track of the
785 * drive in use that has the least number of writers, then if
786 * no unmounted drive is found, we try that drive. This
787 * helps spread the load to the least used drives.
789 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
790 Dmsg3(100, "OK dev=%s == low_drive=%s. JobId=%u\n",
791 dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
794 /* If he wants a free drive, but this one is busy, no go */
795 if (!rctx.PreferMountedVols && dev->is_busy()) {
796 /* Save least used drive */
797 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
798 rctx.num_writers = dev->num_writers + dev->reserved_device;
799 rctx.low_use_drive = dev;
800 Dmsg2(100, "set low use drive=%s num_writers=%d\n", dev->print_name(),
803 Dmsg1(100, "not low use num_writers=%d\n", dev->num_writers+
804 dev->reserved_device);
806 Dmsg1(100, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
807 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
808 jcr->JobId, dev->print_name());
809 queue_reserve_message(jcr);
813 /* Check for prefer mounted volumes */
814 if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
815 Mmsg(jcr->errmsg, _("3606 JobId=%u wants mounted, but drive %s has no Volume.\n"),
816 jcr->JobId, dev->print_name());
817 queue_reserve_message(jcr);
818 Dmsg1(100, "failed: want mounted -- no vol JobId=%u\n", jcr->JobId);
819 return 0; /* No volume mounted */
822 /* Check for exact Volume name match */
823 if (rctx.exact_match && rctx.have_volume &&
824 strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
825 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
826 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
828 queue_reserve_message(jcr);
829 Dmsg2(100, "failed: Not exact match have=%s want=%s\n",
830 dev->VolHdr.VolumeName, rctx.VolumeName);
835 /* Check for unused autochanger drive */
836 if (rctx.autochanger_only && dev->num_writers == 0 &&
837 dev->VolHdr.VolumeName[0] == 0) {
838 /* Device is available but not yet reserved, reserve it for us */
839 Dmsg2(100, "OK Res Unused autochanger %s JobId=%u.\n",
840 dev->print_name(), jcr->JobId);
841 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
842 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
843 return 1; /* reserve drive */
847 * Handle the case that there are no writers
849 if (dev->num_writers == 0) {
850 /* Now check if there are any reservations on the drive */
851 if (dev->reserved_device) {
852 /* Now check if we want the same Pool and pool type */
853 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
854 strcmp(dev->pool_type, dcr->pool_type) == 0) {
855 /* OK, compatible device */
856 Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
857 dev->print_name(), jcr->JobId);
860 /* Drive Pool not suitable for us */
861 Mmsg(jcr->errmsg, _("3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"),
862 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
863 queue_reserve_message(jcr);
864 Dmsg2(100, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
865 dev->pool_name, dcr->pool_name);
868 } else if (dev->can_append()) {
869 /* Device in append mode, check if changing pool */
870 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
871 strcmp(dev->pool_type, dcr->pool_type) == 0) {
872 Dmsg2(100, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
873 dev->print_name(), jcr->JobId);
874 /* OK, compatible device */
877 /* Changing pool, unload old tape if any in drive */
878 Dmsg0(100, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
879 unload_autochanger(dcr, 0);
882 /* Device is available but not yet reserved, reserve it for us */
883 Dmsg2(100, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
885 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
886 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
887 return 1; /* reserve drive */
891 * Check if the device is in append mode with writers (i.e.
892 * available if pool is the same).
894 if (dev->can_append() || dev->num_writers > 0) {
895 /* Yes, now check if we want the same Pool and pool type */
896 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
897 strcmp(dev->pool_type, dcr->pool_type) == 0) {
898 Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
899 dev->print_name(), jcr->JobId);
900 /* OK, compatible device */
903 /* Drive Pool not suitable for us */
904 Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"),
905 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
906 queue_reserve_message(jcr);
907 Dmsg2(100, "failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
908 dev->pool_name, dcr->pool_name);
912 Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
913 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
914 jcr->JobId, dev->print_name());
915 queue_reserve_message(jcr);
916 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
917 return -1; /* error, should not get here */
919 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
920 jcr->JobId, dev->print_name());
921 queue_reserve_message(jcr);
922 Dmsg2(100, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
927 * search_lock is already set on entering this routine
929 static void queue_reserve_message(JCR *jcr)
932 alist *msgs = jcr->reserve_msgs;
939 * Look for duplicate message. If found, do
942 for (i=msgs->size()-1; i >= 0; i--) {
943 msg = (char *)msgs->get(i);
947 /* Comparison based on 4 digit message number */
948 if (strncmp(msg, jcr->errmsg, 4) == 0) {
952 /* Message unique, so insert it */
953 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
957 * Send any reservation messages queued for this jcr
959 void send_drive_reserve_messages(JCR *jcr, BSOCK *user)
966 msgs = jcr->reserve_msgs;
967 if (!msgs || msgs->size() == 0) {
971 for (i=msgs->size()-1; i >= 0; i--) {
972 msg = (char *)msgs->get(i);
974 bnet_fsend(user, " %s", msg);