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);
122 foreach_dlist(vol, vol_list) {
123 if (vol && vol->dev == dcr->dev) {
124 vol_list->remove(vol);
133 vol = (VOLRES *)malloc(sizeof(VOLRES));
134 memset(vol, 0, sizeof(VOLRES));
135 vol->vol_name = bstrdup(VolumeName);
138 nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
144 nvol->dev = dcr->dev;
152 * Search for a Volume name in the Volume list.
154 * Returns: VOLRES entry on success
155 * NULL if the Volume is not in the list
157 VOLRES *find_volume(const char *VolumeName)
161 vol.vol_name = bstrdup(VolumeName);
162 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
169 * Free a Volume from the Volume list
171 * Returns: true if the Volume found and removed from the list
172 * false if the Volume is not in the list
174 bool free_volume(DEVICE *dev)
179 if (dev->VolHdr.VolumeName[0] == 0) {
181 * Our device has no VolumeName listed, but
182 * search the list for any Volume attached to
183 * this device and remove it.
185 foreach_dlist(fvol, vol_list) {
186 if (fvol && fvol->dev == dev) {
187 vol_list->remove(fvol);
188 if (fvol->vol_name) {
189 free(fvol->vol_name);
197 Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
198 vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
199 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
201 vol_list->remove(fvol);
202 free(fvol->vol_name);
206 dev->VolHdr.VolumeName[0] = 0;
212 /* Free volume reserved by this dcr but not attached to a dev */
213 void free_unused_volume(DCR *dcr)
217 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
218 if (vol->dcr == dcr && (vol->dev == NULL ||
219 strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
220 vol_list->remove(vol);
230 * List Volumes -- this should be moved to status.c
232 void list_volumes(BSOCK *user)
235 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
237 bnet_fsend(user, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
239 bnet_fsend(user, "%s\n", vol->vol_name);
244 /* Create the Volume list */
245 void create_volume_list()
247 VOLRES *dummy = NULL;
248 if (vol_list == NULL) {
249 vol_list = New(dlist(dummy, &dummy->link));
253 /* Release all Volumes from the list */
254 void free_volume_list()
260 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
261 Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
268 bool is_volume_in_use(DCR *dcr)
270 VOLRES *vol = find_volume(dcr->VolumeName);
272 return false; /* vol not in list */
274 if (!vol->dev) { /* vol not attached to device */
277 if (dcr->dev == vol->dev) { /* same device OK */
280 if (!vol->dev->is_busy()) {
287 static bool use_storage_cmd(JCR *jcr)
289 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
290 BSOCK *dir = jcr->dir_bsock;
300 memset(&rctx, 0, sizeof(RCTX));
303 * If there are multiple devices, the director sends us
304 * use_device for each device that it wants to use.
306 Dmsg1(100, "<dird: %s", dir->msg);
307 jcr->dirstore = New(alist(10, not_owned_by_alist));
309 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
310 media_type.c_str(), pool_name.c_str(),
311 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
315 unbash_spaces(store_name);
316 unbash_spaces(media_type);
317 unbash_spaces(pool_name);
318 unbash_spaces(pool_type);
319 store = new DIRSTORE;
320 jcr->dirstore->append(store);
321 memset(store, 0, sizeof(DIRSTORE));
322 store->device = New(alist(10));
323 bstrncpy(store->name, store_name, sizeof(store->name));
324 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
325 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
326 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
327 store->append = append;
329 /* Now get all devices */
330 while (bnet_recv(dir) >= 0) {
331 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
335 unbash_spaces(dev_name);
336 store->device->append(bstrdup(dev_name.c_str()));
338 } while (ok && bnet_recv(dir) >= 0);
341 /* This loop is debug code and can be removed */
342 /* ***FIXME**** remove after 1.38 release */
344 foreach_alist(store, jcr->dirstore) {
345 Dmsg4(100, "Storage=%s media_type=%s pool=%s pool_type=%s\n",
346 store->name, store->media_type, store->pool_name,
348 foreach_alist(device_name, store->device) {
349 Dmsg1(100, " Device=%s\n", device_name);
355 * At this point, we have a list of all the Director's Storage
356 * resources indicated for this Job, which include Pool, PoolType,
357 * storage name, and Media type.
358 * Then for each of the Storage resources, we have a list of
359 * device names that were given.
361 * Wiffle through them and find one that can do the backup.
365 * First look for an exact match of Volume name as the
366 * tape may already be mounted.
368 rctx.do_not_wait = true;
369 rctx.exact_match = true;
370 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
373 rctx.exact_match = false;
375 /* Now search if an unused autochanger slot is available */
376 rctx.available_autochanger = true;
377 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
380 rctx.available_autochanger = false;
384 * Make up to two passes. The first with PreferMountedVols possibly
385 * set to true. In that case, we look only for an available
386 * drive with something mounted. If that fails, then we
387 * do a second pass with PerferMountedVols set false.
389 rctx.PreferMountedVols = jcr->PreferMountedVols;
390 if (!rctx.PreferMountedVols) {
391 rctx.do_not_wait = false;
393 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
396 if (rctx.PreferMountedVols) {
397 rctx.PreferMountedVols = false;
398 rctx.do_not_wait = false;
399 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
404 unbash_spaces(dir->msg);
405 pm_strcpy(jcr->errmsg, dir->msg);
406 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
408 Jmsg(jcr, M_FATAL, 0, _("\n"
409 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
410 dev_name.c_str(), media_type.c_str());
411 bnet_fsend(dir, NO_device, dev_name.c_str());
413 for (error=(char*)rctx->errors.first(); error;
414 error=(char*)rctx->errors.next()) {
415 Jmsg(jcr, M_INFO, 0, "%s", error);
418 Dmsg1(100, ">dird: %s", dir->msg);
420 unbash_spaces(dir->msg);
421 pm_strcpy(jcr->errmsg, dir->msg);
423 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
425 bnet_fsend(dir, BAD_use, jcr->errmsg);
426 Dmsg1(100, ">dird: %s", dir->msg);
430 foreach_alist(store, jcr->dirstore) {
431 delete store->device;
434 delete jcr->dirstore;
436 for (error=(char*)rctx->errors.first(); error;
437 error=(char*)rctx->errors.next()) {
446 * Search for a device suitable for this job.
448 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
456 init_jcr_device_wait_timers(jcr);
458 int can_wait = false;
461 foreach_alist(store, jcr->dirstore) {
463 foreach_alist(device_name, store->device) {
465 rctx.device_name = device_name;
466 stat = search_res_for_device(rctx);
467 if (stat == 1) { /* found available device */
470 } else if (stat == 0) { /* device busy */
473 /* otherwise error */
474 // rctx->errors.push(bstrdup(jcr->errmsg));
482 * We did not find a suitable device, so
483 * if there is some device for which we can wait, then
484 * wait and try again until the wait time expires
486 if (rctx.do_not_wait || !can_wait || !wait_for_device(jcr, first)) {
489 first = false; /* first wait complete */
492 for (error=(char*)rctx->errors.first(); error;
493 error=(char*)rctx->errors.next()) {
505 * Search for a particular storage device with particular storage
506 * characteristics (MediaType).
508 static int search_res_for_device(RCTX &rctx)
510 AUTOCHANGER *changer;
511 BSOCK *dir = rctx.jcr->dir_bsock;
515 Dmsg1(100, "Search res for %s\n", rctx.device_name);
516 if (!rctx.available_autochanger) {
517 foreach_res(rctx.device, R_DEVICE) {
518 Dmsg1(100, "Try res=%s\n", rctx.device->hdr.name);
519 /* Find resource, and make sure we were able to open it */
520 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
521 stat = reserve_device(rctx);
525 Dmsg1(220, "Got: %s", dir->msg);
526 bash_spaces(rctx.device_name);
527 ok = bnet_fsend(dir, OK_device, rctx.device_name);
528 Dmsg1(100, ">dird dev: %s", dir->msg);
533 foreach_res(changer, R_AUTOCHANGER) {
534 Dmsg1(100, "Try changer res=%s\n", changer->hdr.name);
535 /* Find resource, and make sure we were able to open it */
536 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
537 /* Try each device in this AutoChanger */
538 foreach_alist(rctx.device, changer->device) {
539 Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
540 stat = reserve_device(rctx);
541 if (stat == -1) { /* hard error */
544 if (stat == 0) { /* must wait, try next one */
548 Dmsg1(100, "Device %s opened.\n", rctx.device_name);
549 pm_strcpy(dev_name, rctx.device->hdr.name);
550 bash_spaces(dev_name);
551 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
552 Dmsg1(100, ">dird changer: %s", dir->msg);
557 return 0; /* nothing found */
561 * Try to reserve a specific device.
563 * Returns: 1 -- OK, have DCR
567 static int reserve_device(RCTX &rctx)
571 const int name_len = MAX_NAME_LENGTH;
573 /* Make sure MediaType is OK */
574 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
578 if (!rctx.device->dev) {
579 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
581 if (!rctx.device->dev) {
582 if (rctx.device->changer_res) {
583 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
584 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
585 rctx.device->hdr.name, rctx.device_name);
587 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
588 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
591 return -1; /* no use waiting */
593 Dmsg1(100, "Found device %s\n", rctx.device->hdr.name);
594 dcr = new_dcr(rctx.jcr, rctx.device->dev);
596 BSOCK *dir = rctx.jcr->dir_bsock;
597 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
598 Dmsg1(100, ">dird: %s", dir->msg);
602 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
603 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
604 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
605 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
606 if (rctx.store->append == SD_APPEND) {
607 if (rctx.exact_match && !rctx.have_volume) {
608 dcr->any_volume = true;
609 if (dir_find_next_appendable_volume(dcr)) {
610 Dmsg1(200, "Looking for Volume=%s\n", dcr->VolumeName);
611 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
612 rctx.have_volume = true;
614 Dmsg0(200, "No next volume found\n");
615 rctx.VolumeName[0] = 0;
618 ok = reserve_device_for_append(dcr, rctx);
619 Dmsg3(200, "dev_name=%s mediatype=%s ok=%d\n", dcr->dev_name, dcr->media_type, ok);
621 ok = reserve_device_for_read(dcr);
624 free_dcr(rctx.jcr->dcr);
631 * We "reserve" the drive by setting the ST_READ bit. No one else
632 * should touch the drive until that is cleared.
633 * This allows the DIR to "reserve" the device before actually
636 static bool reserve_device_for_read(DCR *dcr)
638 DEVICE *dev = dcr->dev;
644 dev->block(BST_DOING_ACQUIRE);
646 if (is_device_unmounted(dev)) {
647 Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
648 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
653 if (dev->is_busy()) {
654 Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
655 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
656 Mmsg1(jcr->errmsg, _("Device %s is busy.\n"),
672 * We reserve the device for appending by incrementing the
673 * reserved_device. We do virtually all the same work that
674 * is done in acquire_device_for_append(), but we do
675 * not attempt to mount the device. This routine allows
676 * the DIR to reserve multiple devices before *really*
677 * starting the job. It also permits the SD to refuse
678 * certain devices (not up, ...).
680 * Note, in reserving a device, if the device is for the
681 * same pool and the same pool type, then it is acceptable.
682 * The Media Type has already been checked. If we are
683 * the first tor reserve the device, we put the pool
684 * name and pool type in the device record.
686 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
689 DEVICE *dev = dcr->dev;
694 dev->block(BST_DOING_ACQUIRE);
696 if (dev->can_read()) {
697 Mmsg1(jcr->errmsg, _("Device %s is busy reading.\n"), dev->print_name());
698 Dmsg1(100, "%s", jcr->errmsg);
702 if (is_device_unmounted(dev)) {
703 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"), dev->print_name());
704 Dmsg1(100, "%s", jcr->errmsg);
708 Dmsg1(190, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
710 if (can_reserve_drive(dcr, rctx) != 1) {
711 Dmsg1(100, "%s", jcr->errmsg);
715 dev->reserved_device++;
716 Dmsg1(200, "Inc reserve=%d\n", dev->reserved_device);
717 dcr->reserved_device = true;
726 * Returns: 1 if drive can be reserved
727 * 0 if we should wait
730 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
732 DEVICE *dev = dcr->dev;
735 /* Check for prefer mounted volumes */
736 if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
737 Mmsg0(jcr->errmsg, _("Want mounted Volume, drive is empty\n"));
738 Dmsg0(200, "want mounted -- no vol\n");
739 return 0; /* No volume mounted */
742 /* Check for exact Volume name match */
743 if (rctx.exact_match && rctx.have_volume &&
744 strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
745 Mmsg2(jcr->errmsg, _("Not exact match have=%s want=%s\n"),
746 dev->VolHdr.VolumeName, rctx.VolumeName);
747 Dmsg2(200, "Not exact match have=%s want=%s\n",
748 dev->VolHdr.VolumeName, rctx.VolumeName);
752 /* Check for unused autochanger drive */
753 if (rctx.available_autochanger && dev->num_writers == 0 &&
754 dev->VolHdr.VolumeName[0] == 0) {
755 /* Device is available but not yet reserved, reserve it for us */
756 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
757 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
758 return 1; /* reserve drive */
762 * Handle the case that there are no writers
764 if (dev->num_writers == 0) {
765 /* Now check if there are any reservations on the drive */
766 if (dev->reserved_device) {
767 /* Now check if we want the same Pool and pool type */
768 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
769 strcmp(dev->pool_type, dcr->pool_type) == 0) {
770 /* OK, compatible device */
771 Dmsg0(200, "got dev: num_writers=0, reserved, pool matches\n");
774 /* Drive not suitable for us */
775 Mmsg2(jcr->errmsg, _("Drive busy wrong pool: num_writers=0, reserved, pool=%s wanted=%s\n"),
776 dev->pool_name, dcr->pool_name);
777 Dmsg2(200, "busy: num_writers=0, reserved, pool=%s wanted=%s\n",
778 dev->pool_name, dcr->pool_name);
781 } else if (dev->can_append()) {
782 /* Device in append mode, check if changing pool */
783 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
784 strcmp(dev->pool_type, dcr->pool_type) == 0) {
785 Dmsg0(200, "got dev: num_writers=0, can_append, pool matches\n");
786 /* OK, compatible device */
789 /* Changing pool, unload old tape if any in drive */
790 Dmsg0(200, "got dev: num_writers=0, reserved, pool change\n");
791 unload_autochanger(dcr, 0);
794 /* Device is available but not yet reserved, reserve it for us */
795 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
796 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
797 return 1; /* reserve drive */
801 * Check if the device is in append mode with writers (i.e.
802 * available if pool is the same).
804 if (dev->can_append() || dev->num_writers > 0) {
805 Dmsg0(190, "device already in append.\n");
806 /* Yes, now check if we want the same Pool and pool type */
807 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
808 strcmp(dev->pool_type, dcr->pool_type) == 0) {
809 Dmsg0(200, "got dev: num_writers>=0, can_append, pool matches\n");
810 /* OK, compatible device */
813 /* Drive not suitable for us */
814 Mmsg(jcr->errmsg, _("Wanted Pool \"%s\", but device %s is using Pool \"%s\" .\n"),
815 dcr->pool_name, dev->print_name(), dev->pool_name);
816 Dmsg2(200, "busy: num_writers>0, can_append, pool=%s wanted=%s\n",
817 dev->pool_name, dcr->pool_name);
821 Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
822 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
823 return -1; /* error, should not get here */