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);
121 foreach_dlist(vol, vol_list) {
122 if (vol && vol->dev == dcr->dev) {
123 vol_list->remove(vol);
132 vol = (VOLRES *)malloc(sizeof(VOLRES));
133 memset(vol, 0, sizeof(VOLRES));
134 vol->vol_name = bstrdup(VolumeName);
137 nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
143 nvol->dev = dcr->dev;
151 * Search for a Volume name in the Volume list.
153 * Returns: VOLRES entry on success
154 * NULL if the Volume is not in the list
156 VOLRES *find_volume(const char *VolumeName)
160 vol.vol_name = bstrdup(VolumeName);
161 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
168 * Free a Volume from the Volume list
170 * Returns: true if the Volume found and removed from the list
171 * false if the Volume is not in the list
173 bool free_volume(DEVICE *dev)
178 if (dev->VolHdr.VolumeName[0] == 0) {
180 * Our device has no VolumeName listed, but
181 * search the list for any Volume attached to
182 * this device and remove it.
184 foreach_dlist(fvol, vol_list) {
185 if (fvol && fvol->dev == dev) {
186 vol_list->remove(fvol);
187 if (fvol->vol_name) {
188 free(fvol->vol_name);
196 Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
197 vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
198 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
200 vol_list->remove(fvol);
201 free(fvol->vol_name);
205 dev->VolHdr.VolumeName[0] = 0;
211 /* Free volume reserved by this dcr but not attached to a dev */
212 void free_unused_volume(DCR *dcr)
216 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
217 if (vol->dcr == dcr && (vol->dev == NULL ||
218 strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
219 vol_list->remove(vol);
229 * List Volumes -- this should be moved to status.c
231 void list_volumes(BSOCK *user)
234 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
236 bnet_fsend(user, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
238 bnet_fsend(user, "%s\n", vol->vol_name);
243 /* Create the Volume list */
244 void create_volume_list()
246 VOLRES *dummy = NULL;
247 if (vol_list == NULL) {
248 vol_list = New(dlist(dummy, &dummy->link));
252 /* Release all Volumes from the list */
253 void free_volume_list()
259 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
260 Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
267 bool is_volume_in_use(DCR *dcr)
269 VOLRES *vol = find_volume(dcr->VolumeName);
271 return false; /* vol not in list */
273 if (!vol->dev) { /* vol not attached to device */
276 if (dcr->dev == vol->dev) { /* same device OK */
279 if (!vol->dev->is_busy()) {
286 static bool use_storage_cmd(JCR *jcr)
288 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
289 BSOCK *dir = jcr->dir_bsock;
299 memset(&rctx, 0, sizeof(RCTX));
302 * If there are multiple devices, the director sends us
303 * use_device for each device that it wants to use.
305 Dmsg1(100, "<dird: %s", dir->msg);
306 jcr->dirstore = New(alist(10, not_owned_by_alist));
308 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
309 media_type.c_str(), pool_name.c_str(),
310 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
314 unbash_spaces(store_name);
315 unbash_spaces(media_type);
316 unbash_spaces(pool_name);
317 unbash_spaces(pool_type);
318 store = new DIRSTORE;
319 jcr->dirstore->append(store);
320 memset(store, 0, sizeof(DIRSTORE));
321 store->device = New(alist(10));
322 bstrncpy(store->name, store_name, sizeof(store->name));
323 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
324 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
325 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
326 store->append = append;
328 /* Now get all devices */
329 while (bnet_recv(dir) >= 0) {
330 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
334 unbash_spaces(dev_name);
335 store->device->append(bstrdup(dev_name.c_str()));
337 } while (ok && bnet_recv(dir) >= 0);
340 /* This loop is debug code and can be removed */
341 /* ***FIXME**** remove after 1.38 release */
343 foreach_alist(store, jcr->dirstore) {
344 Dmsg4(100, "Storage=%s media_type=%s pool=%s pool_type=%s\n",
345 store->name, store->media_type, store->pool_name,
347 foreach_alist(device_name, store->device) {
348 Dmsg1(100, " Device=%s\n", device_name);
354 * At this point, we have a list of all the Director's Storage
355 * resources indicated for this Job, which include Pool, PoolType,
356 * storage name, and Media type.
357 * Then for each of the Storage resources, we have a list of
358 * device names that were given.
360 * Wiffle through them and find one that can do the backup.
364 * First look for an exact match of Volume name as the
365 * tape may already be mounted.
367 rctx.do_not_wait = true;
368 rctx.exact_match = true;
369 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
372 rctx.exact_match = false;
374 /* Now search if an unused autochanger slot is available */
375 rctx.available_autochanger = true;
376 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
379 rctx.available_autochanger = false;
383 * Make up to two passes. The first with PreferMountedVols possibly
384 * set to true. In that case, we look only for an available
385 * drive with something mounted. If that fails, then we
386 * do a second pass with PerferMountedVols set false.
388 rctx.PreferMountedVols = jcr->PreferMountedVols;
389 if (!rctx.PreferMountedVols) {
390 rctx.do_not_wait = false;
392 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
395 if (rctx.PreferMountedVols) {
396 rctx.PreferMountedVols = false;
397 rctx.do_not_wait = false;
398 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
403 unbash_spaces(dir->msg);
404 pm_strcpy(jcr->errmsg, dir->msg);
405 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
407 Jmsg(jcr, M_FATAL, 0, _("\n"
408 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
409 dev_name.c_str(), media_type.c_str());
410 bnet_fsend(dir, NO_device, dev_name.c_str());
412 for (error=(char*)rctx->errors.first(); error;
413 error=(char*)rctx->errors.next()) {
414 Jmsg(jcr, M_INFO, 0, "%s", error);
417 Dmsg1(100, ">dird: %s", dir->msg);
419 unbash_spaces(dir->msg);
420 pm_strcpy(jcr->errmsg, dir->msg);
422 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
424 bnet_fsend(dir, BAD_use, jcr->errmsg);
425 Dmsg1(100, ">dird: %s", dir->msg);
429 foreach_alist(store, jcr->dirstore) {
430 delete store->device;
433 delete jcr->dirstore;
435 for (error=(char*)rctx->errors.first(); error;
436 error=(char*)rctx->errors.next()) {
445 * Search for a device suitable for this job.
447 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
455 init_jcr_device_wait_timers(jcr);
457 int can_wait = false;
460 foreach_alist(store, jcr->dirstore) {
462 foreach_alist(device_name, store->device) {
464 rctx.device_name = device_name;
465 stat = search_res_for_device(rctx);
466 if (stat == 1) { /* found available device */
469 } else if (stat == 0) { /* device busy */
472 /* otherwise error */
473 // rctx->errors.push(bstrdup(jcr->errmsg));
481 * We did not find a suitable device, so
482 * if there is some device for which we can wait, then
483 * wait and try again until the wait time expires
485 if (rctx.do_not_wait || !can_wait || !wait_for_device(jcr, first)) {
488 first = false; /* first wait complete */
491 for (error=(char*)rctx->errors.first(); error;
492 error=(char*)rctx->errors.next()) {
504 * Search for a particular storage device with particular storage
505 * characteristics (MediaType).
507 static int search_res_for_device(RCTX &rctx)
509 AUTOCHANGER *changer;
510 BSOCK *dir = rctx.jcr->dir_bsock;
514 Dmsg1(100, "Search res for %s\n", rctx.device_name);
515 if (!rctx.available_autochanger) {
516 foreach_res(rctx.device, R_DEVICE) {
517 Dmsg1(100, "Try res=%s\n", rctx.device->hdr.name);
518 /* Find resource, and make sure we were able to open it */
519 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
520 stat = reserve_device(rctx);
524 Dmsg1(220, "Got: %s", dir->msg);
525 bash_spaces(rctx.device_name);
526 ok = bnet_fsend(dir, OK_device, rctx.device_name);
527 Dmsg1(100, ">dird dev: %s", dir->msg);
532 foreach_res(changer, R_AUTOCHANGER) {
533 Dmsg1(100, "Try changer res=%s\n", changer->hdr.name);
534 /* Find resource, and make sure we were able to open it */
535 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
536 /* Try each device in this AutoChanger */
537 foreach_alist(rctx.device, changer->device) {
538 Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
539 stat = reserve_device(rctx);
540 if (stat == -1) { /* hard error */
543 if (stat == 0) { /* must wait, try next one */
547 Dmsg1(100, "Device %s opened.\n", rctx.device_name);
548 pm_strcpy(dev_name, rctx.device->hdr.name);
549 bash_spaces(dev_name);
550 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
551 Dmsg1(100, ">dird changer: %s", dir->msg);
556 return 0; /* nothing found */
560 * Try to reserve a specific device.
562 * Returns: 1 -- OK, have DCR
566 static int reserve_device(RCTX &rctx)
570 const int name_len = MAX_NAME_LENGTH;
572 /* Make sure MediaType is OK */
573 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
577 if (!rctx.device->dev) {
578 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
580 if (!rctx.device->dev) {
581 if (rctx.device->changer_res) {
582 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
583 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
584 rctx.device->hdr.name, rctx.device_name);
586 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
587 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
590 return -1; /* no use waiting */
592 Dmsg1(100, "Found device %s\n", rctx.device->hdr.name);
593 dcr = new_dcr(rctx.jcr, rctx.device->dev);
595 BSOCK *dir = rctx.jcr->dir_bsock;
596 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
597 Dmsg1(100, ">dird: %s", dir->msg);
601 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
602 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
603 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
604 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
605 if (rctx.store->append == SD_APPEND) {
606 if (rctx.exact_match && !rctx.have_volume) {
607 dcr->any_volume = true;
608 if (dir_find_next_appendable_volume(dcr)) {
609 Dmsg1(200, "Looking for Volume=%s\n", dcr->VolumeName);
610 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
611 rctx.have_volume = true;
613 Dmsg0(200, "No next volume found\n");
614 rctx.VolumeName[0] = 0;
617 ok = reserve_device_for_append(dcr, rctx);
618 Dmsg3(200, "dev_name=%s mediatype=%s ok=%d\n", dcr->dev_name, dcr->media_type, ok);
620 ok = reserve_device_for_read(dcr);
623 free_dcr(rctx.jcr->dcr);
630 * We "reserve" the drive by setting the ST_READ bit. No one else
631 * should touch the drive until that is cleared.
632 * This allows the DIR to "reserve" the device before actually
635 static bool reserve_device_for_read(DCR *dcr)
637 DEVICE *dev = dcr->dev;
643 dev->block(BST_DOING_ACQUIRE);
645 if (is_device_unmounted(dev)) {
646 Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
647 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
652 if (dev->is_busy()) {
653 Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
654 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
655 Mmsg1(jcr->errmsg, _("Device %s is busy.\n"),
671 * We reserve the device for appending by incrementing the
672 * reserved_device. We do virtually all the same work that
673 * is done in acquire_device_for_append(), but we do
674 * not attempt to mount the device. This routine allows
675 * the DIR to reserve multiple devices before *really*
676 * starting the job. It also permits the SD to refuse
677 * certain devices (not up, ...).
679 * Note, in reserving a device, if the device is for the
680 * same pool and the same pool type, then it is acceptable.
681 * The Media Type has already been checked. If we are
682 * the first tor reserve the device, we put the pool
683 * name and pool type in the device record.
685 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
688 DEVICE *dev = dcr->dev;
693 dev->block(BST_DOING_ACQUIRE);
695 if (dev->can_read()) {
696 Mmsg1(jcr->errmsg, _("Device %s is busy reading.\n"), dev->print_name());
697 Dmsg1(100, "%s", jcr->errmsg);
701 if (is_device_unmounted(dev)) {
702 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"), dev->print_name());
703 Dmsg1(100, "%s", jcr->errmsg);
707 Dmsg1(190, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
709 if (can_reserve_drive(dcr, rctx) != 1) {
710 Dmsg1(100, "%s", jcr->errmsg);
714 dev->reserved_device++;
715 Dmsg1(200, "Inc reserve=%d\n", dev->reserved_device);
716 dcr->reserved_device = true;
725 * Returns: 1 if drive can be reserved
726 * 0 if we should wait
729 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
731 DEVICE *dev = dcr->dev;
734 /* Check for prefer mounted volumes */
735 if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
736 Mmsg0(jcr->errmsg, _("Want mounted Volume, drive is empty\n"));
737 Dmsg0(200, "want mounted -- no vol\n");
738 return 0; /* No volume mounted */
741 /* Check for exact Volume name match */
742 if (rctx.exact_match && rctx.have_volume &&
743 strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
744 Mmsg2(jcr->errmsg, _("Not exact match have=%s want=%s\n"),
745 dev->VolHdr.VolumeName, rctx.VolumeName);
746 Dmsg2(200, "Not exact match have=%s want=%s\n",
747 dev->VolHdr.VolumeName, rctx.VolumeName);
751 /* Check for unused autochanger drive */
752 if (rctx.available_autochanger && dev->num_writers == 0 &&
753 dev->VolHdr.VolumeName[0] == 0) {
754 /* Device is available but not yet reserved, reserve it for us */
755 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
756 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
757 return 1; /* reserve drive */
761 * Handle the case that there are no writers
763 if (dev->num_writers == 0) {
764 /* Now check if there are any reservations on the drive */
765 if (dev->reserved_device) {
766 /* Now check if we want the same Pool and pool type */
767 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
768 strcmp(dev->pool_type, dcr->pool_type) == 0) {
769 /* OK, compatible device */
770 Dmsg0(200, "got dev: num_writers=0, reserved, pool matches\n");
773 /* Drive not suitable for us */
774 Mmsg2(jcr->errmsg, _("Drive busy wrong pool: num_writers=0, reserved, pool=%s wanted=%s\n"),
775 dev->pool_name, dcr->pool_name);
776 Dmsg2(200, "busy: num_writers=0, reserved, pool=%s wanted=%s\n",
777 dev->pool_name, dcr->pool_name);
780 } else if (dev->can_append()) {
781 /* Device in append mode, check if changing pool */
782 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
783 strcmp(dev->pool_type, dcr->pool_type) == 0) {
784 Dmsg0(200, "got dev: num_writers=0, can_append, pool matches\n");
785 /* OK, compatible device */
788 /* Changing pool, unload old tape if any in drive */
789 Dmsg0(200, "got dev: num_writers=0, reserved, pool change\n");
790 unload_autochanger(dcr, 0);
793 /* Device is available but not yet reserved, reserve it for us */
794 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
795 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
796 return 1; /* reserve drive */
800 * Check if the device is in append mode with writers (i.e.
801 * available if pool is the same).
803 if (dev->can_append() || dev->num_writers > 0) {
804 Dmsg0(190, "device already in append.\n");
805 /* Yes, now check if we want the same Pool and pool type */
806 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
807 strcmp(dev->pool_type, dcr->pool_type) == 0) {
808 Dmsg0(200, "got dev: num_writers>=0, can_append, pool matches\n");
809 /* OK, compatible device */
812 /* Drive not suitable for us */
813 Mmsg(jcr->errmsg, _("Wanted Pool \"%s\", but device %s is using Pool \"%s\" .\n"),
814 dcr->pool_name, dev->print_name(), dev->pool_name);
815 Dmsg2(200, "busy: num_writers>0, can_append, pool=%s wanted=%s\n",
816 dev->pool_name, dcr->pool_name);
820 Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
821 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
822 return -1; /* error, should not get here */