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 * Use Device command from Director
31 * He tells is what Device Name to use, the Media Type,
32 * the Pool Name, and the Pool Type.
34 * Ensure that the device exists and is opened, then store
35 * the media and pool info in the JCR. This class is used
36 * only temporarily in this file.
42 char name[MAX_NAME_LENGTH];
43 char media_type[MAX_NAME_LENGTH];
44 char pool_name[MAX_NAME_LENGTH];
45 char pool_type[MAX_NAME_LENGTH];
55 DEVICE *low_use_drive; /* Low use drive candidate */
56 int num_writers; /* for selecting low use drive */
57 bool try_low_use_drive; /* see if low use drive available */
58 bool any_drive; /* Accept any drive if set */
59 bool PreferMountedVols; /* Prefer volumes already mounted */
60 bool exact_match; /* Want exact volume */
61 bool have_volume; /* Have DIR suggested vol name */
62 bool suitable_device; /* at least one device is suitable */
63 bool autochanger_only; /* look at autochangers only */
64 char VolumeName[MAX_NAME_LENGTH]; /* Vol name suggested by DIR */
67 static dlist *vol_list = NULL;
68 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
69 static pthread_mutex_t search_lock = PTHREAD_MUTEX_INITIALIZER;
71 /* Forward referenced functions */
72 static int can_reserve_drive(DCR *dcr, RCTX &rctx);
73 static int search_res_for_device(RCTX &rctx);
74 static int reserve_device(RCTX &rctx);
75 static bool reserve_device_for_read(DCR *dcr);
76 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
77 static bool use_storage_cmd(JCR *jcr);
78 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx);
79 static void queue_reserve_message(JCR *jcr);
81 /* Requests from the Director daemon */
82 static char use_storage[] = "use storage=%127s media_type=%127s "
83 "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
84 static char use_device[] = "use device=%127s\n";
86 /* Responses sent to Director daemon */
87 static char OK_device[] = "3000 OK use device device=%s\n";
88 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
89 static char BAD_use[] = "3913 Bad use command: %s\n";
91 bool use_cmd(JCR *jcr)
94 * Get the device, media, and pool information
96 if (!use_storage_cmd(jcr)) {
97 set_jcr_job_status(jcr, JS_ErrorTerminated);
98 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
104 static int my_compare(void *item1, void *item2)
106 return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
111 * Put a new Volume entry in the Volume list. This
112 * effectively reserves the volume so that it will
113 * not be mounted again.
115 * Return: VOLRES entry on success
116 * NULL if the Volume is already in the list
118 VOLRES *new_volume(DCR *dcr, const char *VolumeName)
122 Dmsg1(400, "new_volume %s\n", VolumeName);
126 foreach_dlist(vol, vol_list) {
127 if (vol && vol->dev == dcr->dev) {
128 vol_list->remove(vol);
137 vol = (VOLRES *)malloc(sizeof(VOLRES));
138 memset(vol, 0, sizeof(VOLRES));
139 vol->vol_name = bstrdup(VolumeName);
142 nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
148 nvol->dev = dcr->dev;
156 * Search for a Volume name in the Volume list.
158 * Returns: VOLRES entry on success
159 * NULL if the Volume is not in the list
161 VOLRES *find_volume(const char *VolumeName)
165 vol.vol_name = bstrdup(VolumeName);
166 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
173 * Free a Volume from the Volume list
175 * Returns: true if the Volume found and removed from the list
176 * false if the Volume is not in the list
178 bool free_volume(DEVICE *dev)
183 if (dev->VolHdr.VolumeName[0] == 0) {
185 * Our device has no VolumeName listed, but
186 * search the list for any Volume attached to
187 * this device and remove it.
189 foreach_dlist(fvol, vol_list) {
190 if (fvol && fvol->dev == dev) {
191 vol_list->remove(fvol);
192 if (fvol->vol_name) {
193 free(fvol->vol_name);
201 Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
202 vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
203 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
205 vol_list->remove(fvol);
206 free(fvol->vol_name);
210 dev->VolHdr.VolumeName[0] = 0;
216 /* Free volume reserved by this dcr but not attached to a dev */
217 void free_unused_volume(DCR *dcr)
221 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
222 if (vol->dcr == dcr && (vol->dev == NULL ||
223 strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
224 vol_list->remove(vol);
234 * List Volumes -- this should be moved to status.c
236 void list_volumes(BSOCK *user)
239 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
241 bnet_fsend(user, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
243 bnet_fsend(user, "%s\n", vol->vol_name);
248 /* Create the Volume list */
249 void create_volume_list()
251 VOLRES *dummy = NULL;
252 if (vol_list == NULL) {
253 vol_list = New(dlist(dummy, &dummy->link));
257 /* Release all Volumes from the list */
258 void free_volume_list()
264 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
265 Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
272 bool is_volume_in_use(DCR *dcr)
274 VOLRES *vol = find_volume(dcr->VolumeName);
276 return false; /* vol not in list */
278 if (!vol->dev) { /* vol not attached to device */
281 if (dcr->dev == vol->dev) { /* same device OK */
284 if (!vol->dev->is_busy()) {
292 * We get the following type of information:
294 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
298 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
302 static bool use_storage_cmd(JCR *jcr)
304 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
305 BSOCK *dir = jcr->dir_bsock;
314 memset(&rctx, 0, sizeof(RCTX));
317 * If there are multiple devices, the director sends us
318 * use_device for each device that it wants to use.
320 jcr->dirstore = New(alist(10, not_owned_by_alist));
321 msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
323 Dmsg1(100, "<dird: %s", dir->msg);
324 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
325 media_type.c_str(), pool_name.c_str(),
326 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
330 unbash_spaces(store_name);
331 unbash_spaces(media_type);
332 unbash_spaces(pool_name);
333 unbash_spaces(pool_type);
334 store = new DIRSTORE;
335 jcr->dirstore->append(store);
336 memset(store, 0, sizeof(DIRSTORE));
337 store->device = New(alist(10));
338 bstrncpy(store->name, store_name, sizeof(store->name));
339 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
340 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
341 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
342 store->append = append;
344 /* Now get all devices */
345 while (bnet_recv(dir) >= 0) {
346 Dmsg1(100, "<dird device: %s", dir->msg);
347 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
351 unbash_spaces(dev_name);
352 store->device->append(bstrdup(dev_name.c_str()));
354 } while (ok && bnet_recv(dir) >= 0);
357 /* This loop is debug code and can be removed */
358 /* ***FIXME**** remove after 1.38 release */
360 foreach_alist(store, jcr->dirstore) {
361 Dmsg5(100, "Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n",
362 store->name, store->media_type, store->pool_name,
363 store->pool_type, store->append);
364 foreach_alist(device_name, store->device) {
365 Dmsg1(100, " Device=%s\n", device_name);
370 init_jcr_device_wait_timers(jcr);
372 * At this point, we have a list of all the Director's Storage
373 * resources indicated for this Job, which include Pool, PoolType,
374 * storage name, and Media type.
375 * Then for each of the Storage resources, we have a list of
376 * device names that were given.
378 * Wiffle through them and find one that can do the backup.
381 bool first = true; /* print wait message once */
382 for ( ; !job_canceled(jcr); ) {
383 P(search_lock); /* only one thread at a time */
384 while ((msg = (char *)msgs->pop())) {
387 rctx.suitable_device = false;
388 rctx.have_volume = false;
389 rctx.any_drive = false;
390 if (!jcr->PreferMountedVols) {
391 /* Look for unused drives in autochangers */
392 rctx.num_writers = 20000000; /* start with impossible number */
393 rctx.low_use_drive = NULL;
394 rctx.PreferMountedVols = false;
395 rctx.exact_match = false;
396 rctx.autochanger_only = true;
397 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
398 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
399 rctx.autochanger_only, rctx.any_drive);
400 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
403 /* Look through all drives possibly for low_use drive */
404 if (rctx.low_use_drive) {
405 rctx.try_low_use_drive = true;
406 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
409 rctx.try_low_use_drive = false;
411 rctx.autochanger_only = false;
412 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
413 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
414 rctx.autochanger_only, rctx.any_drive);
415 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
419 /* Look for an exact match all drives */
420 rctx.PreferMountedVols = true;
421 rctx.exact_match = true;
422 rctx.autochanger_only = false;
423 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
424 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
425 rctx.autochanger_only, rctx.any_drive);
426 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
429 /* Look for any mounted drive */
430 rctx.exact_match = false;
431 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
432 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
433 rctx.autochanger_only, rctx.any_drive);
434 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
438 rctx.any_drive = true;
439 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
440 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
441 rctx.autochanger_only, rctx.any_drive);
442 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
445 /* Unlock before possible wait */
447 if (!rctx.suitable_device || !wait_for_device(jcr, first)) {
448 break; /* Get out, failure ... */
451 bnet_sig(dir, BNET_HEARTBEAT); /* Inform Dir that we are alive */
453 /* Note if !ok then search_lock is already cleared */
460 * If we get here, there are no suitable devices available, which
461 * means nothing configured. If a device is suitable but busy
462 * with another Volume, we will not come here.
465 unbash_spaces(dir->msg);
466 pm_strcpy(jcr->errmsg, dir->msg);
467 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
469 Jmsg(jcr, M_FATAL, 0, _("\n"
470 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
471 dev_name.c_str(), media_type.c_str());
472 bnet_fsend(dir, NO_device, dev_name.c_str());
474 Dmsg1(100, ">dird: %s", dir->msg);
476 unbash_spaces(dir->msg);
477 pm_strcpy(jcr->errmsg, dir->msg);
479 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
481 bnet_fsend(dir, BAD_use, jcr->errmsg);
482 Dmsg1(100, ">dird: %s", dir->msg);
486 foreach_alist(store, jcr->dirstore) {
487 delete store->device;
490 delete jcr->dirstore;
492 while ((msg = (char *)msgs->pop())) {
496 jcr->reserve_msgs = NULL;
503 * Search for a device suitable for this job.
505 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
512 * For each storage device that the user specified, we
513 * search and see if there is a resource for that device.
515 Dmsg4(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
516 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
517 rctx.autochanger_only);
519 foreach_alist(store, jcr->dirstore) {
521 foreach_alist(device_name, store->device) {
523 rctx.device_name = device_name;
524 stat = search_res_for_device(rctx);
525 if (stat == 1) { /* found available device */
526 Dmsg1(100, "Suitable device found=%s\n", device_name);
529 } else if (stat == 0) { /* device busy */
530 Dmsg1(100, "Suitable busy device found=%s\n", device_name);
532 /* otherwise error */
533 Dmsg0(100, "No suitable device found.\n");
545 * Search for a particular storage device with particular storage
546 * characteristics (MediaType).
548 static int search_res_for_device(RCTX &rctx)
550 AUTOCHANGER *changer;
551 BSOCK *dir = rctx.jcr->dir_bsock;
555 Dmsg1(100, "Search res for %s\n", rctx.device_name);
556 /* Look through Autochangers first */
557 foreach_res(changer, R_AUTOCHANGER) {
558 Dmsg1(150, "Try match changer res=%s\n", changer->hdr.name);
559 /* Find resource, and make sure we were able to open it */
560 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
561 /* Try each device in this AutoChanger */
562 foreach_alist(rctx.device, changer->device) {
563 Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
564 stat = reserve_device(rctx);
565 if (stat != 1) { /* try another device */
569 if (rctx.store->append == SD_APPEND) {
570 Dmsg2(100, "Device %s reserved=%d.\n", rctx.device_name,
571 rctx.jcr->dcr->dev->reserved_device);
573 Dmsg2(100, "Device %s reserved=%d.\n", rctx.device_name,
574 rctx.jcr->read_dcr->dev->reserved_device);
576 pm_strcpy(dev_name, rctx.device->hdr.name);
577 bash_spaces(dev_name);
578 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
579 Dmsg1(100, ">dird changer: %s", dir->msg);
585 /* Now if requested look through regular devices */
586 if (!rctx.autochanger_only) {
587 foreach_res(rctx.device, R_DEVICE) {
588 Dmsg1(150, "Try match res=%s\n", rctx.device->hdr.name);
589 /* Find resource, and make sure we were able to open it */
590 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
591 stat = reserve_device(rctx);
595 Dmsg1(220, "Got: %s", dir->msg);
596 bash_spaces(rctx.device_name);
597 ok = bnet_fsend(dir, OK_device, rctx.device_name);
598 Dmsg1(100, ">dird dev: %s", dir->msg);
603 return -1; /* nothing found */
607 * Try to reserve a specific device.
609 * Returns: 1 -- OK, have DCR
613 static int reserve_device(RCTX &rctx)
617 const int name_len = MAX_NAME_LENGTH;
619 /* Make sure MediaType is OK */
620 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
624 /* Make sure device exists -- i.e. we can stat() it */
625 if (!rctx.device->dev) {
626 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
628 if (!rctx.device->dev) {
629 if (rctx.device->changer_res) {
630 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
631 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
632 rctx.device->hdr.name, rctx.device_name);
634 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
635 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
638 return -1; /* no use waiting */
641 rctx.suitable_device = true;
642 Dmsg2(100, "Try reserve %s JobId=%u\n", rctx.device->hdr.name,
644 dcr = new_dcr(rctx.jcr, rctx.device->dev);
646 BSOCK *dir = rctx.jcr->dir_bsock;
647 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
648 Dmsg1(100, ">dird: %s", dir->msg);
651 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
652 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
653 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
654 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
655 if (rctx.store->append == SD_APPEND) {
656 if (rctx.exact_match && !rctx.have_volume) {
657 dcr->any_volume = true;
658 if (dir_find_next_appendable_volume(dcr)) {
659 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
660 Dmsg2(100, "JobId=%u looking for Volume=%s\n", rctx.jcr->JobId, rctx.VolumeName);
661 rctx.have_volume = true;
663 Dmsg0(100, "No next volume found\n");
664 rctx.VolumeName[0] = 0;
667 ok = reserve_device_for_append(dcr, rctx);
670 Dmsg5(100, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
671 dcr->dev->reserved_device,
672 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
675 ok = reserve_device_for_read(dcr);
677 rctx.jcr->read_dcr = dcr;
678 Dmsg5(100, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
679 dcr->dev->reserved_device,
680 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
685 Dmsg0(100, "Not OK.\n");
692 * We "reserve" the drive by setting the ST_READ bit. No one else
693 * should touch the drive until that is cleared.
694 * This allows the DIR to "reserve" the device before actually
697 static bool reserve_device_for_read(DCR *dcr)
699 DEVICE *dev = dcr->dev;
707 if (is_device_unmounted(dev)) {
708 Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
709 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
710 jcr->JobId, dev->print_name());
711 queue_reserve_message(jcr);
715 if (dev->is_busy()) {
716 Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
717 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
718 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
719 jcr->JobId, dev->print_name());
720 queue_reserve_message(jcr);
735 * We reserve the device for appending by incrementing the
736 * reserved_device. We do virtually all the same work that
737 * is done in acquire_device_for_append(), but we do
738 * not attempt to mount the device. This routine allows
739 * the DIR to reserve multiple devices before *really*
740 * starting the job. It also permits the SD to refuse
741 * certain devices (not up, ...).
743 * Note, in reserving a device, if the device is for the
744 * same pool and the same pool type, then it is acceptable.
745 * The Media Type has already been checked. If we are
746 * the first tor reserve the device, we put the pool
747 * name and pool type in the device record.
749 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
752 DEVICE *dev = dcr->dev;
759 /* If device is being read, we cannot write it */
760 if (dev->can_read()) {
761 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
762 jcr->JobId, dev->print_name());
763 Dmsg1(100, "%s", jcr->errmsg);
764 queue_reserve_message(jcr);
768 /* If device is unmounted, we are out of luck */
769 if (is_device_unmounted(dev)) {
770 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
771 jcr->JobId, dev->print_name());
772 Dmsg1(100, "%s", jcr->errmsg);
773 queue_reserve_message(jcr);
777 Dmsg1(100, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
779 /* Now do detailed tests ... */
780 if (can_reserve_drive(dcr, rctx) != 1) {
781 Dmsg0(100, "can_reserve_drive!=1\n");
785 dev->reserved_device++;
786 Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
787 dev->print_name(), dev);
788 dcr->reserved_device = true;
797 * Returns: 1 if drive can be reserved
798 * 0 if we should wait
799 * -1 on error or impossibility
801 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
803 DEVICE *dev = dcr->dev;
806 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
807 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
808 rctx.autochanger_only, rctx.any_drive);
810 /* setting any_drive overrides PreferMountedVols flag */
811 if (!rctx.any_drive) {
813 * When PreferMountedVols is set, we keep track of the
814 * drive in use that has the least number of writers, then if
815 * no unmounted drive is found, we try that drive. This
816 * helps spread the load to the least used drives.
818 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
819 Dmsg3(100, "OK dev=%s == low_drive=%s. JobId=%u\n",
820 dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
823 /* If he wants a free drive, but this one is busy, no go */
824 if (!rctx.PreferMountedVols && dev->is_busy()) {
825 /* Save least used drive */
826 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
827 rctx.num_writers = dev->num_writers + dev->reserved_device;
828 rctx.low_use_drive = dev;
829 Dmsg2(100, "set low use drive=%s num_writers=%d\n", dev->print_name(),
832 Dmsg1(100, "not low use num_writers=%d\n", dev->num_writers+
833 dev->reserved_device);
835 Dmsg1(100, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
836 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
837 jcr->JobId, dev->print_name());
838 queue_reserve_message(jcr);
842 /* Check for prefer mounted volumes */
843 if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
844 Mmsg(jcr->errmsg, _("3606 JobId=%u wants mounted, but drive %s has no Volume.\n"),
845 jcr->JobId, dev->print_name());
846 queue_reserve_message(jcr);
847 Dmsg1(100, "failed: want mounted -- no vol JobId=%u\n", jcr->JobId);
848 return 0; /* No volume mounted */
851 /* Check for exact Volume name match */
852 if (rctx.exact_match && rctx.have_volume &&
853 strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
854 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
855 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
857 queue_reserve_message(jcr);
858 Dmsg2(100, "failed: Not exact match have=%s want=%s\n",
859 dev->VolHdr.VolumeName, rctx.VolumeName);
864 /* Check for unused autochanger drive */
865 if (rctx.autochanger_only && dev->num_writers == 0 &&
866 dev->VolHdr.VolumeName[0] == 0) {
867 /* Device is available but not yet reserved, reserve it for us */
868 Dmsg2(100, "OK Res Unused autochanger %s JobId=%u.\n",
869 dev->print_name(), jcr->JobId);
870 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
871 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
872 return 1; /* reserve drive */
876 * Handle the case that there are no writers
878 if (dev->num_writers == 0) {
879 /* Now check if there are any reservations on the drive */
880 if (dev->reserved_device) {
881 /* Now check if we want the same Pool and pool type */
882 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
883 strcmp(dev->pool_type, dcr->pool_type) == 0) {
884 /* OK, compatible device */
885 Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
886 dev->print_name(), jcr->JobId);
889 /* Drive Pool not suitable for us */
890 Mmsg(jcr->errmsg, _("3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"),
891 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
892 queue_reserve_message(jcr);
893 Dmsg2(100, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
894 dev->pool_name, dcr->pool_name);
897 } else if (dev->can_append()) {
898 /* Device in append mode, check if changing pool */
899 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
900 strcmp(dev->pool_type, dcr->pool_type) == 0) {
901 Dmsg2(100, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
902 dev->print_name(), jcr->JobId);
903 /* OK, compatible device */
906 /* Changing pool, unload old tape if any in drive */
907 Dmsg0(100, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
908 unload_autochanger(dcr, 0);
911 /* Device is available but not yet reserved, reserve it for us */
912 Dmsg2(100, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
914 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
915 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
916 return 1; /* reserve drive */
920 * Check if the device is in append mode with writers (i.e.
921 * available if pool is the same).
923 if (dev->can_append() || dev->num_writers > 0) {
924 /* Yes, now check if we want the same Pool and pool type */
925 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
926 strcmp(dev->pool_type, dcr->pool_type) == 0) {
927 Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
928 dev->print_name(), jcr->JobId);
929 /* OK, compatible device */
932 /* Drive Pool not suitable for us */
933 Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"),
934 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
935 queue_reserve_message(jcr);
936 Dmsg2(100, "failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
937 dev->pool_name, dcr->pool_name);
941 Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
942 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
943 jcr->JobId, dev->print_name());
944 queue_reserve_message(jcr);
945 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
946 return -1; /* error, should not get here */
948 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
949 jcr->JobId, dev->print_name());
950 queue_reserve_message(jcr);
951 Dmsg2(100, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
956 * search_lock is already set on entering this routine
958 static void queue_reserve_message(JCR *jcr)
961 alist *msgs = jcr->reserve_msgs;
968 * Look for duplicate message. If found, do
971 for (i=msgs->size()-1; i >= 0; i--) {
972 msg = (char *)msgs->get(i);
976 /* Comparison based on 4 digit message number */
977 if (strncmp(msg, jcr->errmsg, 4) == 0) {
981 /* Message unique, so insert it */
982 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
986 * Send any reservation messages queued for this jcr
988 void send_drive_reserve_messages(JCR *jcr, BSOCK *user)
995 msgs = jcr->reserve_msgs;
996 if (!msgs || msgs->size() == 0) {
1000 for (i=msgs->size()-1; i >= 0; i--) {
1001 msg = (char *)msgs->get(i);
1003 bnet_fsend(user, " %s", msg);