2 * Drive reservation functions for Storage Daemon
6 * Split from job.c and acquire.c June 2005
12 Copyright (C) 2000-2005 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);
80 /* Requests from the Director daemon */
81 static char use_storage[] = "use storage=%127s media_type=%127s "
82 "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
83 static char use_device[] = "use device=%127s\n";
85 /* Responses sent to Director daemon */
86 static char OK_device[] = "3000 OK use device device=%s\n";
87 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
88 static char BAD_use[] = "3913 Bad use command: %s\n";
90 bool use_cmd(JCR *jcr)
93 * Get the device, media, and pool information
95 if (!use_storage_cmd(jcr)) {
96 set_jcr_job_status(jcr, JS_ErrorTerminated);
97 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
103 static int my_compare(void *item1, void *item2)
105 return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
110 * Put a new Volume entry in the Volume list. This
111 * effectively reserves the volume so that it will
112 * not be mounted again.
114 * Return: VOLRES entry on success
115 * NULL if the Volume is already in the list
117 VOLRES *new_volume(DCR *dcr, const char *VolumeName)
121 Dmsg1(400, "new_volume %s\n", VolumeName);
125 foreach_dlist(vol, vol_list) {
126 if (vol && vol->dev == dcr->dev) {
127 vol_list->remove(vol);
136 vol = (VOLRES *)malloc(sizeof(VOLRES));
137 memset(vol, 0, sizeof(VOLRES));
138 vol->vol_name = bstrdup(VolumeName);
141 nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
147 nvol->dev = dcr->dev;
155 * Search for a Volume name in the Volume list.
157 * Returns: VOLRES entry on success
158 * NULL if the Volume is not in the list
160 VOLRES *find_volume(const char *VolumeName)
164 vol.vol_name = bstrdup(VolumeName);
165 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
172 * Free a Volume from the Volume list
174 * Returns: true if the Volume found and removed from the list
175 * false if the Volume is not in the list
177 bool free_volume(DEVICE *dev)
182 if (dev->VolHdr.VolumeName[0] == 0) {
184 * Our device has no VolumeName listed, but
185 * search the list for any Volume attached to
186 * this device and remove it.
188 foreach_dlist(fvol, vol_list) {
189 if (fvol && fvol->dev == dev) {
190 vol_list->remove(fvol);
191 if (fvol->vol_name) {
192 free(fvol->vol_name);
200 Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
201 vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
202 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
204 vol_list->remove(fvol);
205 free(fvol->vol_name);
209 dev->VolHdr.VolumeName[0] = 0;
215 /* Free volume reserved by this dcr but not attached to a dev */
216 void free_unused_volume(DCR *dcr)
220 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
221 if (vol->dcr == dcr && (vol->dev == NULL ||
222 strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
223 vol_list->remove(vol);
233 * List Volumes -- this should be moved to status.c
235 void list_volumes(BSOCK *user)
238 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
240 bnet_fsend(user, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
242 bnet_fsend(user, "%s\n", vol->vol_name);
247 /* Create the Volume list */
248 void create_volume_list()
250 VOLRES *dummy = NULL;
251 if (vol_list == NULL) {
252 vol_list = New(dlist(dummy, &dummy->link));
256 /* Release all Volumes from the list */
257 void free_volume_list()
263 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
264 Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
271 bool is_volume_in_use(DCR *dcr)
273 VOLRES *vol = find_volume(dcr->VolumeName);
275 return false; /* vol not in list */
277 if (!vol->dev) { /* vol not attached to device */
280 if (dcr->dev == vol->dev) { /* same device OK */
283 if (!vol->dev->is_busy()) {
291 * We get the following type of information:
293 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
297 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
301 static bool use_storage_cmd(JCR *jcr)
303 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
304 BSOCK *dir = jcr->dir_bsock;
311 memset(&rctx, 0, sizeof(RCTX));
314 * If there are multiple devices, the director sends us
315 * use_device for each device that it wants to use.
317 jcr->dirstore = New(alist(10, not_owned_by_alist));
319 Dmsg1(100, "<dird: %s", dir->msg);
320 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
321 media_type.c_str(), pool_name.c_str(),
322 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
326 unbash_spaces(store_name);
327 unbash_spaces(media_type);
328 unbash_spaces(pool_name);
329 unbash_spaces(pool_type);
330 store = new DIRSTORE;
331 jcr->dirstore->append(store);
332 memset(store, 0, sizeof(DIRSTORE));
333 store->device = New(alist(10));
334 bstrncpy(store->name, store_name, sizeof(store->name));
335 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
336 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
337 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
338 store->append = append;
340 /* Now get all devices */
341 while (bnet_recv(dir) >= 0) {
342 Dmsg1(100, "<dird device: %s", dir->msg);
343 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
347 unbash_spaces(dev_name);
348 store->device->append(bstrdup(dev_name.c_str()));
350 } while (ok && bnet_recv(dir) >= 0);
353 /* This loop is debug code and can be removed */
354 /* ***FIXME**** remove after 1.38 release */
356 foreach_alist(store, jcr->dirstore) {
357 Dmsg4(100, "Storage=%s media_type=%s pool=%s pool_type=%s\n",
358 store->name, store->media_type, store->pool_name,
360 foreach_alist(device_name, store->device) {
361 Dmsg1(100, " Device=%s\n", device_name);
367 * At this point, we have a list of all the Director's Storage
368 * resources indicated for this Job, which include Pool, PoolType,
369 * storage name, and Media type.
370 * Then for each of the Storage resources, we have a list of
371 * device names that were given.
373 * Wiffle through them and find one that can do the backup.
376 bool first = true; /* print wait message once */
377 for ( ; !job_canceled(jcr); ) {
378 rctx.suitable_device = false;
379 rctx.have_volume = false;
380 rctx.any_drive = false;
381 if (!jcr->PreferMountedVols) {
382 /* Look for unused drives in autochangers */
383 rctx.num_writers = 20000000; /* start with impossible number */
384 rctx.low_use_drive = NULL;
385 rctx.PreferMountedVols = false;
386 rctx.exact_match = false;
387 rctx.autochanger_only = true;
388 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
389 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
390 rctx.autochanger_only, rctx.any_drive);
391 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
394 /* Look through all drives possibly for low_use drive */
395 if (rctx.low_use_drive) {
396 rctx.try_low_use_drive = true;
397 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
400 rctx.try_low_use_drive = false;
402 rctx.autochanger_only = false;
403 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
404 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
405 rctx.autochanger_only, rctx.any_drive);
406 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
410 /* Look for an exact match all drives */
411 rctx.PreferMountedVols = true;
412 rctx.exact_match = true;
413 rctx.autochanger_only = false;
414 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
415 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
416 rctx.autochanger_only, rctx.any_drive);
417 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
420 /* Look for any mounted drive */
421 rctx.exact_match = false;
422 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
423 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
424 rctx.autochanger_only, rctx.any_drive);
425 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
429 rctx.any_drive = true;
430 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
431 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
432 rctx.autochanger_only, rctx.any_drive);
433 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
436 if (!rctx.suitable_device || !wait_for_device(jcr, first)) {
437 break; /* Get out, failure ... */
440 bnet_sig(dir, BNET_HEARTBEAT); /* Inform Dir that we are alive */
444 * If we get here, there are no suitable devices available, which
445 * means nothing configured. If a device is suitable but busy
446 * with another Volume, we will not come here.
449 unbash_spaces(dir->msg);
450 pm_strcpy(jcr->errmsg, dir->msg);
451 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
453 Jmsg(jcr, M_FATAL, 0, _("\n"
454 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
455 dev_name.c_str(), media_type.c_str());
456 bnet_fsend(dir, NO_device, dev_name.c_str());
458 Dmsg1(100, ">dird: %s", dir->msg);
460 unbash_spaces(dir->msg);
461 pm_strcpy(jcr->errmsg, dir->msg);
463 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
465 bnet_fsend(dir, BAD_use, jcr->errmsg);
466 Dmsg1(100, ">dird: %s", dir->msg);
470 foreach_alist(store, jcr->dirstore) {
471 delete store->device;
474 delete jcr->dirstore;
476 while (error=(char*)rctx->errors.first()) {
485 * Search for a device suitable for this job.
487 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
494 * For each storage device that the user specified, we
495 * search and see if there is a resource for that device.
497 Dmsg4(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
498 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
499 rctx.autochanger_only);
500 init_jcr_device_wait_timers(jcr);
503 foreach_alist(store, jcr->dirstore) {
505 foreach_alist(device_name, store->device) {
507 rctx.device_name = device_name;
508 stat = search_res_for_device(rctx);
509 if (stat == 1) { /* found available device */
510 rctx.suitable_device = true;
511 Dmsg1(100, "Suitable device found=%s\n", device_name);
514 } else if (stat == 0) { /* device busy */
515 Dmsg1(100, "Suitable busy device found=%s\n", device_name);
516 rctx.suitable_device = true; /* but it is busy, so continue looking */
518 /* otherwise error */
530 * Search for a particular storage device with particular storage
531 * characteristics (MediaType).
533 static int search_res_for_device(RCTX &rctx)
535 AUTOCHANGER *changer;
536 BSOCK *dir = rctx.jcr->dir_bsock;
540 Dmsg1(100, "Search res for %s\n", rctx.device_name);
541 /* Look through Autochangers first */
542 foreach_res(changer, R_AUTOCHANGER) {
543 Dmsg1(150, "Try match changer res=%s\n", changer->hdr.name);
544 /* Find resource, and make sure we were able to open it */
545 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
546 /* Try each device in this AutoChanger */
547 foreach_alist(rctx.device, changer->device) {
548 Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
549 stat = reserve_device(rctx);
550 if (stat != 1) { /* try another device */
554 if (rctx.store->append == SD_APPEND) {
555 Dmsg2(100, "Device %s reserved=%d.\n", rctx.device_name,
556 rctx.jcr->dcr->dev->reserved_device);
558 Dmsg2(100, "Device %s reserved=%d.\n", rctx.device_name,
559 rctx.jcr->read_dcr->dev->reserved_device);
561 pm_strcpy(dev_name, rctx.device->hdr.name);
562 bash_spaces(dev_name);
563 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
564 Dmsg1(100, ">dird changer: %s", dir->msg);
570 /* Now if requested look through regular devices */
571 if (!rctx.autochanger_only) {
572 foreach_res(rctx.device, R_DEVICE) {
573 Dmsg1(150, "Try match res=%s\n", rctx.device->hdr.name);
574 /* Find resource, and make sure we were able to open it */
575 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
576 stat = reserve_device(rctx);
580 Dmsg1(220, "Got: %s", dir->msg);
581 bash_spaces(rctx.device_name);
582 ok = bnet_fsend(dir, OK_device, rctx.device_name);
583 Dmsg1(100, ">dird dev: %s", dir->msg);
588 return -1; /* nothing found */
592 * Try to reserve a specific device.
594 * Returns: 1 -- OK, have DCR
598 static int reserve_device(RCTX &rctx)
602 const int name_len = MAX_NAME_LENGTH;
604 /* Make sure MediaType is OK */
605 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
609 /* Make sure device exists -- i.e. we can stat() it */
610 if (!rctx.device->dev) {
611 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
613 if (!rctx.device->dev) {
614 if (rctx.device->changer_res) {
615 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
616 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
617 rctx.device->hdr.name, rctx.device_name);
619 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
620 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
623 return -1; /* no use waiting */
626 Dmsg2(100, "Try reserve %s jobid=%d\n", rctx.device->hdr.name,
628 dcr = new_dcr(rctx.jcr, rctx.device->dev);
630 BSOCK *dir = rctx.jcr->dir_bsock;
631 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
632 Dmsg1(100, ">dird: %s", dir->msg);
635 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
636 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
637 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
638 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
639 if (rctx.store->append == SD_APPEND) {
640 if (rctx.exact_match && !rctx.have_volume) {
641 dcr->any_volume = true;
642 if (dir_find_next_appendable_volume(dcr)) {
643 Dmsg1(100, "Looking for Volume=%s\n", dcr->VolumeName);
644 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
645 rctx.have_volume = true;
647 Dmsg0(100, "No next volume found\n");
648 rctx.VolumeName[0] = 0;
651 ok = reserve_device_for_append(dcr, rctx);
654 Dmsg5(100, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
655 dcr->dev->reserved_device,
656 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
659 ok = reserve_device_for_read(dcr);
661 rctx.jcr->read_dcr = dcr;
662 Dmsg5(100, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
663 dcr->dev->reserved_device,
664 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
669 Dmsg0(100, "Not OK.\n");
676 * We "reserve" the drive by setting the ST_READ bit. No one else
677 * should touch the drive until that is cleared.
678 * This allows the DIR to "reserve" the device before actually
681 static bool reserve_device_for_read(DCR *dcr)
683 DEVICE *dev = dcr->dev;
691 if (is_device_unmounted(dev)) {
692 Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
693 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
698 if (dev->is_busy()) {
699 Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
700 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
701 Mmsg1(jcr->errmsg, _("Device %s is busy.\n"),
717 * We reserve the device for appending by incrementing the
718 * reserved_device. We do virtually all the same work that
719 * is done in acquire_device_for_append(), but we do
720 * not attempt to mount the device. This routine allows
721 * the DIR to reserve multiple devices before *really*
722 * starting the job. It also permits the SD to refuse
723 * certain devices (not up, ...).
725 * Note, in reserving a device, if the device is for the
726 * same pool and the same pool type, then it is acceptable.
727 * The Media Type has already been checked. If we are
728 * the first tor reserve the device, we put the pool
729 * name and pool type in the device record.
731 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
734 DEVICE *dev = dcr->dev;
741 /* If device is being read, we cannot write it */
742 if (dev->can_read()) {
743 Mmsg1(jcr->errmsg, _("Device %s is busy reading.\n"), dev->print_name());
744 Dmsg1(100, "%s", jcr->errmsg);
748 /* If device is unmounted, we are out of luck */
749 if (is_device_unmounted(dev)) {
750 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"), dev->print_name());
751 Dmsg1(100, "%s", jcr->errmsg);
755 Dmsg1(100, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
757 /* Now do detailed tests ... */
758 if (can_reserve_drive(dcr, rctx) != 1) {
759 Dmsg0(100, "can_reserve_drive!=1\n");
763 dev->reserved_device++;
764 Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device,
765 dev->print_name(), dev);
766 dcr->reserved_device = true;
775 * Returns: 1 if drive can be reserved
776 * 0 if we should wait
777 * -1 on error or impossibility
779 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
781 DEVICE *dev = dcr->dev;
784 Dmsg5(100, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
785 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
786 rctx.autochanger_only, rctx.any_drive);
788 /* setting any_drive overrides PreferMountedVols flag */
789 if (!rctx.any_drive) {
791 * When PreferMountedVols is set, we keep track of the
792 * drive in use that has the least number of writers, then if
793 * no unmounted drive is found, we try that drive. This
794 * helps spread the load to the least used drives.
796 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
797 Dmsg3(100, "OK dev=%s == low_drive=%s. JobId=%d\n",
798 dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
801 /* If he wants a free drive, but this one is busy, no go */
802 if (!rctx.PreferMountedVols && dev->is_busy()) {
803 /* Save least used drive */
804 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
805 rctx.num_writers = dev->num_writers + dev->reserved_device;
806 rctx.low_use_drive = dev;
807 Dmsg2(100, "set low use drive=%s num_writers=%d\n", dev->print_name(),
810 Dmsg1(100, "not low use num_writers=%d\n", dev->num_writers+
811 dev->reserved_device);
813 Dmsg1(100, "failed: !prefMnt && busy. JobId=%d\n", jcr->JobId);
817 /* Check for prefer mounted volumes */
818 if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
819 Dmsg1(100, "failed: want mounted -- no vol JobId=%d\n", jcr->JobId);
820 return 0; /* No volume mounted */
823 /* Check for exact Volume name match */
824 if (rctx.exact_match && rctx.have_volume &&
825 strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
826 Dmsg2(100, "failed: Not exact match have=%s want=%s\n",
827 dev->VolHdr.VolumeName, rctx.VolumeName);
832 /* Check for unused autochanger drive */
833 if (rctx.autochanger_only && dev->num_writers == 0 &&
834 dev->VolHdr.VolumeName[0] == 0) {
835 /* Device is available but not yet reserved, reserve it for us */
836 Dmsg2(100, "OK Res Unused autochanger %s JobId=%d.\n",
837 dev->print_name(), jcr->JobId);
838 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
839 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
840 return 1; /* reserve drive */
844 * Handle the case that there are no writers
846 if (dev->num_writers == 0) {
847 /* Now check if there are any reservations on the drive */
848 if (dev->reserved_device) {
849 /* Now check if we want the same Pool and pool type */
850 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
851 strcmp(dev->pool_type, dcr->pool_type) == 0) {
852 /* OK, compatible device */
853 Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%d\n",
854 dev->print_name(), jcr->JobId);
857 /* Drive not suitable for us */
858 Dmsg2(100, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
859 dev->pool_name, dcr->pool_name);
862 } else if (dev->can_append()) {
863 /* Device in append mode, check if changing pool */
864 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
865 strcmp(dev->pool_type, dcr->pool_type) == 0) {
866 Dmsg2(100, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%d\n",
867 dev->print_name(), jcr->JobId);
868 /* OK, compatible device */
871 /* Changing pool, unload old tape if any in drive */
872 Dmsg0(100, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
873 unload_autochanger(dcr, 0);
876 /* Device is available but not yet reserved, reserve it for us */
877 Dmsg2(100, "OK Dev avail reserved %s JobId=%d\n", dev->print_name(),
879 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
880 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
881 return 1; /* reserve drive */
885 * Check if the device is in append mode with writers (i.e.
886 * available if pool is the same).
888 if (dev->can_append() || dev->num_writers > 0) {
889 /* Yes, now check if we want the same Pool and pool type */
890 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
891 strcmp(dev->pool_type, dcr->pool_type) == 0) {
892 Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%d\n",
893 dev->print_name(), jcr->JobId);
894 /* OK, compatible device */
897 /* Drive not suitable for us */
898 Dmsg2(100, "failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
899 dev->pool_name, dcr->pool_name);
903 Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
904 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
905 return -1; /* error, should not get here */
907 Dmsg2(100, "failed: No reserve %s JobId=%d\n", dev->print_name(), jcr->JobId);