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];
56 bool PreferMountedVols;
60 bool available_autochanger;
61 char VolumeName[MAX_NAME_LENGTH];
64 static dlist *vol_list = NULL;
65 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
66 static pthread_mutex_t search_lock = PTHREAD_MUTEX_INITIALIZER;
68 /* Forward referenced functions */
69 static int can_reserve_drive(DCR *dcr, RCTX &rctx);
70 static int search_res_for_device(RCTX &rctx);
71 static int reserve_device(RCTX &rctx);
72 static bool reserve_device_for_read(DCR *dcr);
73 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
74 static bool use_storage_cmd(JCR *jcr);
75 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx);
77 /* Requests from the Director daemon */
78 static char use_storage[] = "use storage=%127s media_type=%127s "
79 "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
80 static char use_device[] = "use device=%127s\n";
82 /* Responses sent to Director daemon */
83 static char OK_device[] = "3000 OK use device device=%s\n";
84 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
85 static char BAD_use[] = "3913 Bad use command: %s\n";
87 bool use_cmd(JCR *jcr)
90 * Get the device, media, and pool information
92 if (!use_storage_cmd(jcr)) {
93 set_jcr_job_status(jcr, JS_ErrorTerminated);
94 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
100 static int my_compare(void *item1, void *item2)
102 return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
107 * Put a new Volume entry in the Volume list. This
108 * effectively reserves the volume so that it will
109 * not be mounted again.
111 * Return: VOLRES entry on success
112 * NULL if the Volume is already in the list
114 VOLRES *new_volume(DCR *dcr, const char *VolumeName)
118 Dmsg1(400, "new_volume %s\n", VolumeName);
119 vol = (VOLRES *)malloc(sizeof(VOLRES));
120 memset(vol, 0, sizeof(VOLRES));
121 vol->vol_name = bstrdup(VolumeName);
125 nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
131 nvol->dev = dcr->dev;
139 * Search for a Volume name in the Volume list.
141 * Returns: VOLRES entry on success
142 * NULL if the Volume is not in the list
144 VOLRES *find_volume(const char *VolumeName)
147 vol.vol_name = bstrdup(VolumeName);
149 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
156 * Free a Volume from the Volume list
158 * Returns: true if the Volume found and removed from the list
159 * false if the Volume is not in the list
161 bool free_volume(DEVICE *dev)
165 if (dev->VolHdr.VolumeName[0] == 0) {
167 * Our device has no VolumeName listed, but
168 * search the list for any Volume attached to
169 * this device and remove it.
172 foreach_dlist(fvol, vol_list) {
173 if (fvol && fvol->dev == dev) {
174 vol_list->remove(fvol);
175 if (fvol->vol_name) {
176 free(fvol->vol_name);
185 Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
186 vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
188 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
190 vol_list->remove(fvol);
191 free(fvol->vol_name);
196 dev->VolHdr.VolumeName[0] = 0;
200 /* Free volume reserved by this dcr but not attached to a dev */
201 void free_unused_volume(DCR *dcr)
205 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
206 if (vol->dcr == dcr && (vol->dev == NULL ||
207 strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
208 vol_list->remove(vol);
218 * List Volumes -- this should be moved to status.c
220 void list_volumes(BSOCK *user)
223 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
225 bnet_fsend(user, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
227 bnet_fsend(user, "%s\n", vol->vol_name);
232 /* Create the Volume list */
233 void create_volume_list()
235 VOLRES *dummy = NULL;
236 if (vol_list == NULL) {
237 vol_list = New(dlist(dummy, &dummy->link));
241 /* Release all Volumes from the list */
242 void free_volume_list()
248 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
249 Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
256 bool is_volume_in_use(DCR *dcr)
258 VOLRES *vol = find_volume(dcr->VolumeName);
260 return false; /* vol not in list */
262 if (!vol->dev) { /* vol not attached to device */
265 if (dcr->dev == vol->dev) { /* same device OK */
268 if (!vol->dev->is_busy()) {
275 static bool use_storage_cmd(JCR *jcr)
277 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
278 BSOCK *dir = jcr->dir_bsock;
288 memset(&rctx, 0, sizeof(RCTX));
291 * If there are multiple devices, the director sends us
292 * use_device for each device that it wants to use.
294 Dmsg1(100, "<dird: %s", dir->msg);
295 jcr->dirstore = New(alist(10, not_owned_by_alist));
297 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
298 media_type.c_str(), pool_name.c_str(),
299 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
303 unbash_spaces(store_name);
304 unbash_spaces(media_type);
305 unbash_spaces(pool_name);
306 unbash_spaces(pool_type);
307 store = new DIRSTORE;
308 jcr->dirstore->append(store);
309 memset(store, 0, sizeof(DIRSTORE));
310 store->device = New(alist(10));
311 bstrncpy(store->name, store_name, sizeof(store->name));
312 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
313 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
314 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
315 store->append = append;
317 /* Now get all devices */
318 while (bnet_recv(dir) >= 0) {
319 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
323 unbash_spaces(dev_name);
324 store->device->append(bstrdup(dev_name.c_str()));
326 } while (ok && bnet_recv(dir) >= 0);
329 /* This loop is debug code and can be removed */
330 /* ***FIXME**** remove after 1.38 release */
332 foreach_alist(store, jcr->dirstore) {
333 Dmsg4(100, "Storage=%s media_type=%s pool=%s pool_type=%s\n",
334 store->name, store->media_type, store->pool_name,
336 foreach_alist(device_name, store->device) {
337 Dmsg1(100, " Device=%s\n", device_name);
343 * At this point, we have a list of all the Director's Storage
344 * resources indicated for this Job, which include Pool, PoolType,
345 * storage name, and Media type.
346 * Then for each of the Storage resources, we have a list of
347 * device names that were given.
349 * Wiffle through them and find one that can do the backup.
353 * First look for an exact match of Volume name as the
354 * tape may already be mounted.
356 rctx.do_not_wait = true;
357 rctx.exact_match = true;
358 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
361 rctx.exact_match = false;
363 /* Now search if an unused autochanger slot is available */
364 rctx.available_autochanger = true;
365 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
368 rctx.available_autochanger = false;
372 * Make up to two passes. The first with PreferMountedVols possibly
373 * set to true. In that case, we look only for an available
374 * drive with something mounted. If that fails, then we
375 * do a second pass with PerferMountedVols set false.
377 rctx.PreferMountedVols = jcr->PreferMountedVols;
378 if (!rctx.PreferMountedVols) {
379 rctx.do_not_wait = false;
381 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
384 if (rctx.PreferMountedVols) {
385 rctx.PreferMountedVols = false;
386 rctx.do_not_wait = false;
387 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
392 unbash_spaces(dir->msg);
393 pm_strcpy(jcr->errmsg, dir->msg);
394 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
396 Jmsg(jcr, M_FATAL, 0, _("\n"
397 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
398 dev_name.c_str(), media_type.c_str());
399 bnet_fsend(dir, NO_device, dev_name.c_str());
401 for (error=(char*)rctx->errors.first(); error;
402 error=(char*)rctx->errors.next()) {
403 Jmsg(jcr, M_INFO, 0, "%s", error);
406 Dmsg1(100, ">dird: %s", dir->msg);
408 unbash_spaces(dir->msg);
409 pm_strcpy(jcr->errmsg, dir->msg);
411 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
413 bnet_fsend(dir, BAD_use, jcr->errmsg);
414 Dmsg1(100, ">dird: %s", dir->msg);
418 foreach_alist(store, jcr->dirstore) {
419 delete store->device;
422 delete jcr->dirstore;
424 for (error=(char*)rctx->errors.first(); error;
425 error=(char*)rctx->errors.next()) {
434 * Search for a device suitable for this job.
436 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
444 init_jcr_device_wait_timers(jcr);
446 int can_wait = false;
449 foreach_alist(store, jcr->dirstore) {
451 foreach_alist(device_name, store->device) {
453 rctx.device_name = device_name;
454 stat = search_res_for_device(rctx);
455 if (stat == 1) { /* found available device */
458 } else if (stat == 0) { /* device busy */
461 /* otherwise error */
462 // rctx->errors.push(bstrdup(jcr->errmsg));
470 * We did not find a suitable device, so
471 * if there is some device for which we can wait, then
472 * wait and try again until the wait time expires
474 if (rctx.do_not_wait || !can_wait || !wait_for_device(jcr, first)) {
477 first = false; /* first wait complete */
480 for (error=(char*)rctx->errors.first(); error;
481 error=(char*)rctx->errors.next()) {
493 * Search for a particular storage device with particular storage
494 * characteristics (MediaType).
496 static int search_res_for_device(RCTX &rctx)
498 AUTOCHANGER *changer;
499 BSOCK *dir = rctx.jcr->dir_bsock;
503 Dmsg1(100, "Search res for %s\n", rctx.device_name);
504 if (!rctx.available_autochanger) {
505 foreach_res(rctx.device, R_DEVICE) {
506 Dmsg1(100, "Try res=%s\n", rctx.device->hdr.name);
507 /* Find resource, and make sure we were able to open it */
508 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
509 stat = reserve_device(rctx);
513 Dmsg1(220, "Got: %s", dir->msg);
514 bash_spaces(rctx.device_name);
515 ok = bnet_fsend(dir, OK_device, rctx.device_name);
516 Dmsg1(100, ">dird dev: %s", dir->msg);
521 foreach_res(changer, R_AUTOCHANGER) {
522 Dmsg1(100, "Try changer res=%s\n", changer->hdr.name);
523 /* Find resource, and make sure we were able to open it */
524 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
525 /* Try each device in this AutoChanger */
526 foreach_alist(rctx.device, changer->device) {
527 Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
528 stat = reserve_device(rctx);
529 if (stat == -1) { /* hard error */
532 if (stat == 0) { /* must wait, try next one */
536 Dmsg1(100, "Device %s opened.\n", rctx.device_name);
537 pm_strcpy(dev_name, rctx.device->hdr.name);
538 bash_spaces(dev_name);
539 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
540 Dmsg1(100, ">dird changer: %s", dir->msg);
545 return 0; /* nothing found */
549 * Try to reserve a specific device.
551 * Returns: 1 -- OK, have DCR
555 static int reserve_device(RCTX &rctx)
559 const int name_len = MAX_NAME_LENGTH;
561 /* Make sure MediaType is OK */
562 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
566 if (!rctx.device->dev) {
567 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
569 if (!rctx.device->dev) {
570 if (rctx.device->changer_res) {
571 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
572 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
573 rctx.device->hdr.name, rctx.device_name);
575 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
576 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
579 return -1; /* no use waiting */
581 Dmsg1(100, "Found device %s\n", rctx.device->hdr.name);
582 dcr = new_dcr(rctx.jcr, rctx.device->dev);
584 BSOCK *dir = rctx.jcr->dir_bsock;
585 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
586 Dmsg1(100, ">dird: %s", dir->msg);
590 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
591 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
592 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
593 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
594 if (rctx.store->append == SD_APPEND) {
595 if (rctx.exact_match && !rctx.have_volume) {
596 dcr->any_volume = true;
597 if (dir_find_next_appendable_volume(dcr)) {
598 Dmsg1(200, "Looking for Volume=%s\n", dcr->VolumeName);
599 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
600 rctx.have_volume = true;
602 Dmsg0(200, "No next volume found\n");
603 rctx.VolumeName[0] = 0;
606 ok = reserve_device_for_append(dcr, rctx);
607 Dmsg3(200, "dev_name=%s mediatype=%s ok=%d\n", dcr->dev_name, dcr->media_type, ok);
609 ok = reserve_device_for_read(dcr);
612 free_dcr(rctx.jcr->dcr);
619 * We "reserve" the drive by setting the ST_READ bit. No one else
620 * should touch the drive until that is cleared.
621 * This allows the DIR to "reserve" the device before actually
624 static bool reserve_device_for_read(DCR *dcr)
626 DEVICE *dev = dcr->dev;
632 dev->block(BST_DOING_ACQUIRE);
634 if (is_device_unmounted(dev)) {
635 Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
636 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
641 if (dev->is_busy()) {
642 Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
643 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
644 Mmsg1(jcr->errmsg, _("Device %s is busy.\n"),
660 * We reserve the device for appending by incrementing the
661 * reserved_device. We do virtually all the same work that
662 * is done in acquire_device_for_append(), but we do
663 * not attempt to mount the device. This routine allows
664 * the DIR to reserve multiple devices before *really*
665 * starting the job. It also permits the SD to refuse
666 * certain devices (not up, ...).
668 * Note, in reserving a device, if the device is for the
669 * same pool and the same pool type, then it is acceptable.
670 * The Media Type has already been checked. If we are
671 * the first tor reserve the device, we put the pool
672 * name and pool type in the device record.
674 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
677 DEVICE *dev = dcr->dev;
682 dev->block(BST_DOING_ACQUIRE);
684 if (dev->can_read()) {
685 Mmsg1(jcr->errmsg, _("Device %s is busy reading.\n"), dev->print_name());
686 Dmsg1(100, "%s", jcr->errmsg);
690 if (is_device_unmounted(dev)) {
691 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"), dev->print_name());
692 Dmsg1(100, "%s", jcr->errmsg);
696 Dmsg1(190, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
698 if (can_reserve_drive(dcr, rctx) != 1) {
699 Dmsg1(100, "%s", jcr->errmsg);
703 dev->reserved_device++;
704 Dmsg1(200, "Inc reserve=%d\n", dev->reserved_device);
705 dcr->reserved_device = true;
714 * Returns: 1 if drive can be reserved
715 * 0 if we should wait
718 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
720 DEVICE *dev = dcr->dev;
723 /* Check for prefer mounted volumes */
724 if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
725 Mmsg0(jcr->errmsg, _("Want mounted Volume, drive is empty\n"));
726 Dmsg0(200, "want mounted -- no vol\n");
727 return 0; /* No volume mounted */
730 /* Check for exact Volume name match */
731 if (rctx.exact_match && rctx.have_volume &&
732 strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
733 Mmsg2(jcr->errmsg, _("Not exact match have=%s want=%s\n"),
734 dev->VolHdr.VolumeName, rctx.VolumeName);
735 Dmsg2(200, "Not exact match have=%s want=%s\n",
736 dev->VolHdr.VolumeName, rctx.VolumeName);
740 /* Check for unused autochanger drive */
741 if (rctx.available_autochanger && dev->num_writers == 0 &&
742 dev->VolHdr.VolumeName[0] == 0) {
743 /* Device is available but not yet reserved, reserve it for us */
744 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
745 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
746 return 1; /* reserve drive */
750 * Handle the case that there are no writers
752 if (dev->num_writers == 0) {
753 /* Now check if there are any reservations on the drive */
754 if (dev->reserved_device) {
755 /* Now check if we want the same Pool and pool type */
756 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
757 strcmp(dev->pool_type, dcr->pool_type) == 0) {
758 /* OK, compatible device */
759 Dmsg0(200, "got dev: num_writers=0, reserved, pool matches\n");
762 /* Drive not suitable for us */
763 Mmsg2(jcr->errmsg, _("Drive busy wrong pool: num_writers=0, reserved, pool=%s wanted=%s\n"),
764 dev->pool_name, dcr->pool_name);
765 Dmsg2(200, "busy: num_writers=0, reserved, pool=%s wanted=%s\n",
766 dev->pool_name, dcr->pool_name);
769 } else if (dev->can_append()) {
770 /* Device in append mode, check if changing pool */
771 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
772 strcmp(dev->pool_type, dcr->pool_type) == 0) {
773 Dmsg0(200, "got dev: num_writers=0, can_append, pool matches\n");
774 /* OK, compatible device */
777 /* Changing pool, unload old tape if any in drive */
778 Dmsg0(200, "got dev: num_writers=0, reserved, pool change\n");
779 unload_autochanger(dcr, 0);
782 /* Device is available but not yet reserved, reserve it for us */
783 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
784 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
785 return 1; /* reserve drive */
789 * Check if the device is in append mode with writers (i.e.
790 * available if pool is the same).
792 if (dev->can_append() || dev->num_writers > 0) {
793 Dmsg0(190, "device already in append.\n");
794 /* Yes, now check if we want the same Pool and pool type */
795 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
796 strcmp(dev->pool_type, dcr->pool_type) == 0) {
797 Dmsg0(200, "got dev: num_writers>=0, can_append, pool matches\n");
798 /* OK, compatible device */
801 /* Drive not suitable for us */
802 Mmsg(jcr->errmsg, _("Wanted Pool \"%s\", but device %s is using Pool \"%s\" .\n"),
803 dcr->pool_name, dev->print_name(), dev->pool_name);
804 Dmsg2(200, "busy: num_writers>0, can_append, pool=%s wanted=%s\n",
805 dev->pool_name, dcr->pool_name);
809 Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
810 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
811 return -1; /* error, should not get here */