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 reserve_device(RCTX &rctx);
37 static bool reserve_device_for_read(DCR *dcr);
38 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
39 static bool use_storage_cmd(JCR *jcr);
40 static void queue_reserve_message(JCR *jcr);
42 /* Requests from the Director daemon */
43 static char use_storage[] = "use storage=%127s media_type=%127s "
44 "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
45 static char use_device[] = "use device=%127s\n";
47 /* Responses sent to Director daemon */
48 static char OK_device[] = "3000 OK use device device=%s\n";
49 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
50 static char BAD_use[] = "3913 Bad use command: %s\n";
52 bool use_cmd(JCR *jcr)
55 * Get the device, media, and pool information
57 if (!use_storage_cmd(jcr)) {
58 set_jcr_job_status(jcr, JS_ErrorTerminated);
59 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
65 static int my_compare(void *item1, void *item2)
67 return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
72 * Put a new Volume entry in the Volume list. This
73 * effectively reserves the volume so that it will
74 * not be mounted again.
76 * Return: VOLRES entry on success
77 * NULL if the Volume is already in the list
79 VOLRES *new_volume(DCR *dcr, const char *VolumeName)
83 Dmsg1(400, "new_volume %s\n", VolumeName);
87 foreach_dlist(vol, vol_list) {
88 if (vol && vol->dev == dcr->dev) {
89 vol_list->remove(vol);
98 vol = (VOLRES *)malloc(sizeof(VOLRES));
99 memset(vol, 0, sizeof(VOLRES));
100 vol->vol_name = bstrdup(VolumeName);
103 nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
109 nvol->dev = dcr->dev;
117 * Search for a Volume name in the Volume list.
119 * Returns: VOLRES entry on success
120 * NULL if the Volume is not in the list
122 VOLRES *find_volume(const char *VolumeName)
126 vol.vol_name = bstrdup(VolumeName);
127 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
134 * Free a Volume from the Volume list
136 * Returns: true if the Volume found and removed from the list
137 * false if the Volume is not in the list
139 bool free_volume(DEVICE *dev)
144 if (dev->VolHdr.VolumeName[0] == 0) {
146 * Our device has no VolumeName listed, but
147 * search the list for any Volume attached to
148 * this device and remove it.
150 foreach_dlist(fvol, vol_list) {
151 if (fvol && fvol->dev == dev) {
152 vol_list->remove(fvol);
153 if (fvol->vol_name) {
154 free(fvol->vol_name);
162 Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
163 vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
164 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
166 vol_list->remove(fvol);
167 free(fvol->vol_name);
171 dev->VolHdr.VolumeName[0] = 0;
177 /* Free volume reserved by this dcr but not attached to a dev */
178 void free_unused_volume(DCR *dcr)
183 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
184 if (vol->dcr == dcr && (vol->dev == NULL ||
185 strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
186 vol_list->remove(vol);
196 * List Volumes -- this should be moved to status.c
198 void list_volumes(BSOCK *user)
201 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
203 bnet_fsend(user, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
205 bnet_fsend(user, "%s\n", vol->vol_name);
210 /* Create the Volume list */
211 void init_volume_list()
213 VOLRES *dummy = NULL;
214 if (vol_list == NULL) {
215 vol_list = New(dlist(dummy, &dummy->link));
219 /* Release all Volumes from the list */
220 void free_volume_list()
226 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
227 Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
234 bool is_volume_in_use(DCR *dcr)
236 VOLRES *vol = find_volume(dcr->VolumeName);
238 return false; /* vol not in list */
240 if (!vol->dev) { /* vol not attached to device */
243 if (dcr->dev == vol->dev) { /* same device OK */
246 if (!vol->dev->is_busy()) {
254 * We get the following type of information:
256 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
260 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
264 static bool use_storage_cmd(JCR *jcr)
266 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
267 BSOCK *dir = jcr->dir_bsock;
276 memset(&rctx, 0, sizeof(RCTX));
279 * If there are multiple devices, the director sends us
280 * use_device for each device that it wants to use.
282 jcr->dirstore = New(alist(10, not_owned_by_alist));
283 msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
285 Dmsg1(100, "<dird: %s", dir->msg);
286 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
287 media_type.c_str(), pool_name.c_str(),
288 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
292 unbash_spaces(store_name);
293 unbash_spaces(media_type);
294 unbash_spaces(pool_name);
295 unbash_spaces(pool_type);
296 store = new DIRSTORE;
297 jcr->dirstore->append(store);
298 memset(store, 0, sizeof(DIRSTORE));
299 store->device = New(alist(10));
300 bstrncpy(store->name, store_name, sizeof(store->name));
301 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
302 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
303 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
304 store->append = append;
306 /* Now get all devices */
307 while (bnet_recv(dir) >= 0) {
308 Dmsg1(100, "<dird device: %s", dir->msg);
309 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
313 unbash_spaces(dev_name);
314 store->device->append(bstrdup(dev_name.c_str()));
316 } while (ok && bnet_recv(dir) >= 0);
319 /* This loop is debug code and can be removed */
320 /* ***FIXME**** remove after 1.38 release */
322 foreach_alist(store, jcr->dirstore) {
323 Dmsg5(100, "Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n",
324 store->name, store->media_type, store->pool_name,
325 store->pool_type, store->append);
326 foreach_alist(device_name, store->device) {
327 Dmsg1(100, " Device=%s\n", device_name);
332 init_jcr_device_wait_timers(jcr);
334 * At this point, we have a list of all the Director's Storage
335 * resources indicated for this Job, which include Pool, PoolType,
336 * storage name, and Media type.
337 * Then for each of the Storage resources, we have a list of
338 * device names that were given.
340 * Wiffle through them and find one that can do the backup.
343 bool first = true; /* print wait message once */
344 rctx.notify_dir = true;
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 void release_msgs(JCR *jcr)
455 alist *msgs = jcr->reserve_msgs;
462 while ((msg = (char *)msgs->pop())) {
466 jcr->reserve_msgs = NULL;
471 * Search for a device suitable for this job.
473 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
480 * For each storage device that the user specified, we
481 * search and see if there is a resource for that device.
483 Dmsg4(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
484 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
485 rctx.autochanger_only);
487 foreach_alist(store, jcr->dirstore) {
489 foreach_alist(device_name, store->device) {
491 rctx.device_name = device_name;
492 stat = search_res_for_device(rctx);
493 if (stat == 1) { /* found available device */
494 Dmsg1(100, "Suitable device found=%s\n", device_name);
497 } else if (stat == 0) { /* device busy */
498 Dmsg1(100, "Suitable device found=%s, not used: busy\n", device_name);
500 /* otherwise error */
501 Dmsg0(100, "No suitable device found.\n");
513 * Search for a particular storage device with particular storage
514 * characteristics (MediaType).
516 int search_res_for_device(RCTX &rctx)
518 AUTOCHANGER *changer;
519 BSOCK *dir = rctx.jcr->dir_bsock;
523 Dmsg1(100, "Search res for %s\n", rctx.device_name);
524 /* Look through Autochangers first */
525 foreach_res(changer, R_AUTOCHANGER) {
526 Dmsg1(150, "Try match changer res=%s\n", changer->hdr.name);
527 /* Find resource, and make sure we were able to open it */
528 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
529 /* Try each device in this AutoChanger */
530 foreach_alist(rctx.device, changer->device) {
531 Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
532 stat = reserve_device(rctx);
533 if (stat != 1) { /* try another device */
537 if (rctx.store->append == SD_APPEND) {
538 Dmsg2(100, "Device %s reserved=%d for append.\n", rctx.device->hdr.name,
539 rctx.jcr->dcr->dev->reserved_device);
541 Dmsg2(100, "Device %s reserved=%d for read.\n", rctx.device->hdr.name,
542 rctx.jcr->read_dcr->dev->reserved_device);
544 if (rctx.notify_dir) {
545 pm_strcpy(dev_name, rctx.device->hdr.name);
546 bash_spaces(dev_name);
547 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
548 Dmsg1(100, ">dird changer: %s", dir->msg);
557 /* Now if requested look through regular devices */
558 if (!rctx.autochanger_only) {
559 foreach_res(rctx.device, R_DEVICE) {
560 Dmsg1(150, "Try match res=%s\n", rctx.device->hdr.name);
561 /* Find resource, and make sure we were able to open it */
562 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
563 stat = reserve_device(rctx);
567 if (rctx.notify_dir) {
568 bash_spaces(rctx.device_name);
569 ok = bnet_fsend(dir, OK_device, rctx.device_name);
570 Dmsg1(100, ">dird dev: %s", dir->msg);
578 return -1; /* nothing found */
582 * Try to reserve a specific device.
584 * Returns: 1 -- OK, have DCR
588 static int reserve_device(RCTX &rctx)
592 const int name_len = MAX_NAME_LENGTH;
594 /* Make sure MediaType is OK */
595 Dmsg2(100, "MediaType device=%s request=%s\n",
596 rctx.device->media_type, rctx.store->media_type);
597 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
601 /* Make sure device exists -- i.e. we can stat() it */
602 if (!rctx.device->dev) {
603 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
605 if (!rctx.device->dev) {
606 if (rctx.device->changer_res) {
607 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
608 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
609 rctx.device->hdr.name, rctx.device_name);
611 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
612 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
615 return -1; /* no use waiting */
618 rctx.suitable_device = true;
619 Dmsg2(100, "Try reserve %s JobId=%u\n", rctx.device->hdr.name,
621 dcr = new_dcr(rctx.jcr, rctx.device->dev);
623 BSOCK *dir = rctx.jcr->dir_bsock;
624 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
625 Dmsg1(100, ">dird: %s", dir->msg);
628 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
629 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
630 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
631 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
632 if (rctx.store->append == SD_APPEND) {
633 if (rctx.exact_match && !rctx.have_volume) {
634 dcr->any_volume = true;
635 if (dir_find_next_appendable_volume(dcr)) {
636 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
637 Dmsg2(100, "JobId=%u looking for Volume=%s\n", rctx.jcr->JobId, rctx.VolumeName);
638 rctx.have_volume = true;
640 Dmsg0(100, "No next volume found\n");
641 rctx.VolumeName[0] = 0;
644 ok = reserve_device_for_append(dcr, rctx);
647 Dmsg5(100, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
648 dcr->dev->reserved_device,
649 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
652 ok = reserve_device_for_read(dcr);
654 rctx.jcr->read_dcr = dcr;
655 Dmsg5(100, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
656 dcr->dev->reserved_device,
657 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
662 Dmsg0(100, "Not OK.\n");
669 * We "reserve" the drive by setting the ST_READ bit. No one else
670 * should touch the drive until that is cleared.
671 * This allows the DIR to "reserve" the device before actually
674 static bool reserve_device_for_read(DCR *dcr)
676 DEVICE *dev = dcr->dev;
684 if (is_device_unmounted(dev)) {
685 Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
686 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
687 jcr->JobId, dev->print_name());
688 queue_reserve_message(jcr);
692 if (dev->is_busy()) {
693 Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
694 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
695 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
696 jcr->JobId, dev->print_name());
697 queue_reserve_message(jcr);
704 dev->reserved_device++;
705 Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
706 dev->print_name(), dev);
707 dcr->reserved_device = true;
716 * We reserve the device for appending by incrementing the
717 * reserved_device. We do virtually all the same work that
718 * is done in acquire_device_for_append(), but we do
719 * not attempt to mount the device. This routine allows
720 * the DIR to reserve multiple devices before *really*
721 * starting the job. It also permits the SD to refuse
722 * certain devices (not up, ...).
724 * Note, in reserving a device, if the device is for the
725 * same pool and the same pool type, then it is acceptable.
726 * The Media Type has already been checked. If we are
727 * the first tor reserve the device, we put the pool
728 * name and pool type in the device record.
730 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
733 DEVICE *dev = dcr->dev;
740 /* If device is being read, we cannot write it */
741 if (dev->can_read()) {
742 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
743 jcr->JobId, dev->print_name());
744 Dmsg1(100, "%s", jcr->errmsg);
745 queue_reserve_message(jcr);
749 /* If device is unmounted, we are out of luck */
750 if (is_device_unmounted(dev)) {
751 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
752 jcr->JobId, dev->print_name());
753 Dmsg1(100, "%s", jcr->errmsg);
754 queue_reserve_message(jcr);
758 Dmsg1(100, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
760 /* Now do detailed tests ... */
761 if (can_reserve_drive(dcr, rctx) != 1) {
762 Dmsg0(100, "can_reserve_drive!=1\n");
766 dev->reserved_device++;
767 Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
768 dev->print_name(), dev);
769 dcr->reserved_device = true;
778 * Returns: 1 if drive can be reserved
779 * 0 if we should wait
780 * -1 on error or impossibility
782 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
784 DEVICE *dev = dcr->dev;
787 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
788 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
789 rctx.autochanger_only, rctx.any_drive);
791 /* setting any_drive overrides PreferMountedVols flag */
792 if (!rctx.any_drive) {
794 * When PreferMountedVols is set, we keep track of the
795 * drive in use that has the least number of writers, then if
796 * no unmounted drive is found, we try that drive. This
797 * helps spread the load to the least used drives.
799 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
800 Dmsg3(100, "OK dev=%s == low_drive=%s. JobId=%u\n",
801 dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
804 /* If he wants a free drive, but this one is busy, no go */
805 if (!rctx.PreferMountedVols && dev->is_busy()) {
806 /* Save least used drive */
807 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
808 rctx.num_writers = dev->num_writers + dev->reserved_device;
809 rctx.low_use_drive = dev;
810 Dmsg2(100, "set low use drive=%s num_writers=%d\n", dev->print_name(),
813 Dmsg1(100, "not low use num_writers=%d\n", dev->num_writers+
814 dev->reserved_device);
816 Dmsg1(100, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
817 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
818 jcr->JobId, dev->print_name());
819 queue_reserve_message(jcr);
823 /* Check for prefer mounted volumes */
824 if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
825 Mmsg(jcr->errmsg, _("3606 JobId=%u wants mounted, but drive %s has no Volume.\n"),
826 jcr->JobId, dev->print_name());
827 queue_reserve_message(jcr);
828 Dmsg1(100, "failed: want mounted -- no vol JobId=%u\n", jcr->JobId);
829 return 0; /* No volume mounted */
832 /* Check for exact Volume name match */
833 if (rctx.exact_match && rctx.have_volume &&
834 strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
835 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
836 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
838 queue_reserve_message(jcr);
839 Dmsg2(100, "failed: Not exact match have=%s want=%s\n",
840 dev->VolHdr.VolumeName, rctx.VolumeName);
845 /* Check for unused autochanger drive */
846 if (rctx.autochanger_only && dev->num_writers == 0 &&
847 dev->VolHdr.VolumeName[0] == 0) {
848 /* Device is available but not yet reserved, reserve it for us */
849 Dmsg2(100, "OK Res Unused autochanger %s JobId=%u.\n",
850 dev->print_name(), jcr->JobId);
851 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
852 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
853 return 1; /* reserve drive */
857 * Handle the case that there are no writers
859 if (dev->num_writers == 0) {
860 /* Now check if there are any reservations on the drive */
861 if (dev->reserved_device) {
862 /* Now check if we want the same Pool and pool type */
863 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
864 strcmp(dev->pool_type, dcr->pool_type) == 0) {
865 /* OK, compatible device */
866 Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
867 dev->print_name(), jcr->JobId);
870 /* Drive Pool not suitable for us */
871 Mmsg(jcr->errmsg, _("3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"),
872 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
873 queue_reserve_message(jcr);
874 Dmsg2(100, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
875 dev->pool_name, dcr->pool_name);
878 } else if (dev->can_append()) {
879 /* Device in append mode, check if changing pool */
880 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
881 strcmp(dev->pool_type, dcr->pool_type) == 0) {
882 Dmsg2(100, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
883 dev->print_name(), jcr->JobId);
884 /* OK, compatible device */
887 /* Changing pool, unload old tape if any in drive */
888 Dmsg0(100, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
889 unload_autochanger(dcr, 0);
892 /* Device is available but not yet reserved, reserve it for us */
893 Dmsg2(100, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
895 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
896 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
897 return 1; /* reserve drive */
901 * Check if the device is in append mode with writers (i.e.
902 * available if pool is the same).
904 if (dev->can_append() || dev->num_writers > 0) {
905 /* Yes, now check if we want the same Pool and pool type */
906 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
907 strcmp(dev->pool_type, dcr->pool_type) == 0) {
908 Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
909 dev->print_name(), jcr->JobId);
910 /* OK, compatible device */
913 /* Drive Pool not suitable for us */
914 Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"),
915 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
916 queue_reserve_message(jcr);
917 Dmsg2(100, "failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
918 dev->pool_name, dcr->pool_name);
922 Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
923 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
924 jcr->JobId, dev->print_name());
925 queue_reserve_message(jcr);
926 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
927 return -1; /* error, should not get here */
929 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
930 jcr->JobId, dev->print_name());
931 queue_reserve_message(jcr);
932 Dmsg2(100, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
937 * search_lock is already set on entering this routine
939 static void queue_reserve_message(JCR *jcr)
942 alist *msgs = jcr->reserve_msgs;
949 * Look for duplicate message. If found, do
952 for (i=msgs->size()-1; i >= 0; i--) {
953 msg = (char *)msgs->get(i);
957 /* Comparison based on 4 digit message number */
958 if (strncmp(msg, jcr->errmsg, 4) == 0) {
962 /* Message unique, so insert it */
963 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
967 * Send any reservation messages queued for this jcr
969 void send_drive_reserve_messages(JCR *jcr, BSOCK *user)
976 msgs = jcr->reserve_msgs;
977 if (!msgs || msgs->size() == 0) {
981 for (i=msgs->size()-1; i >= 0; i--) {
982 msg = (char *)msgs->get(i);
984 bnet_fsend(user, " %s", msg);