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) {
168 Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
169 vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
171 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
173 vol_list->remove(fvol);
174 free(fvol->vol_name);
179 dev->VolHdr.VolumeName[0] = 0;
183 /* Free volume reserved by this dcr but not attached to a dev */
184 void free_unused_volume(DCR *dcr)
188 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
189 if (vol->dcr == dcr && (vol->dev == NULL ||
190 strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
191 vol_list->remove(vol);
201 * List Volumes -- this should be moved to status.c
203 void list_volumes(BSOCK *user)
206 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
207 bnet_fsend(user, "%s\n", vol->vol_name);
211 /* Create the Volume list */
212 void create_volume_list()
214 VOLRES *dummy = NULL;
215 if (vol_list == NULL) {
216 vol_list = New(dlist(dummy, &dummy->link));
220 /* Release all Volumes from the list */
221 void free_volume_list()
227 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
228 Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
235 bool is_volume_in_use(DCR *dcr)
237 VOLRES *vol = find_volume(dcr->VolumeName);
239 return false; /* vol not in list */
241 if (!vol->dev) { /* vol not attached to device */
244 if (dcr->dev == vol->dev) { /* same device OK */
247 if (!vol->dev->is_busy()) {
254 static bool use_storage_cmd(JCR *jcr)
256 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
257 BSOCK *dir = jcr->dir_bsock;
267 memset(&rctx, 0, sizeof(RCTX));
270 * If there are multiple devices, the director sends us
271 * use_device for each device that it wants to use.
273 Dmsg1(100, "<dird: %s", dir->msg);
274 jcr->dirstore = New(alist(10, not_owned_by_alist));
276 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
277 media_type.c_str(), pool_name.c_str(),
278 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
282 unbash_spaces(store_name);
283 unbash_spaces(media_type);
284 unbash_spaces(pool_name);
285 unbash_spaces(pool_type);
286 store = new DIRSTORE;
287 jcr->dirstore->append(store);
288 memset(store, 0, sizeof(DIRSTORE));
289 store->device = New(alist(10));
290 bstrncpy(store->name, store_name, sizeof(store->name));
291 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
292 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
293 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
294 store->append = append;
296 /* Now get all devices */
297 while (bnet_recv(dir) >= 0) {
298 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
302 unbash_spaces(dev_name);
303 store->device->append(bstrdup(dev_name.c_str()));
305 } while (ok && bnet_recv(dir) >= 0);
308 /* This loop is debug code and can be removed */
309 /* ***FIXME**** remove after 1.38 release */
311 foreach_alist(store, jcr->dirstore) {
312 Dmsg4(100, "Storage=%s media_type=%s pool=%s pool_type=%s\n",
313 store->name, store->media_type, store->pool_name,
315 foreach_alist(device_name, store->device) {
316 Dmsg1(100, " Device=%s\n", device_name);
322 * At this point, we have a list of all the Director's Storage
323 * resources indicated for this Job, which include Pool, PoolType,
324 * storage name, and Media type.
325 * Then for each of the Storage resources, we have a list of
326 * device names that were given.
328 * Wiffle through them and find one that can do the backup.
332 * First look for an exact match of Volume name as the
333 * tape may already be mounted.
335 rctx.do_not_wait = true;
336 rctx.exact_match = true;
337 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
340 rctx.exact_match = false;
342 /* Now search if an unused autochanger slot is available */
343 rctx.available_autochanger = true;
344 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
347 rctx.available_autochanger = false;
351 * Make up to two passes. The first with PreferMountedVols possibly
352 * set to true. In that case, we look only for an available
353 * drive with something mounted. If that fails, then we
354 * do a second pass with PerferMountedVols set false.
356 rctx.PreferMountedVols = jcr->PreferMountedVols;
357 if (!rctx.PreferMountedVols) {
358 rctx.do_not_wait = false;
360 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
363 if (rctx.PreferMountedVols) {
364 rctx.PreferMountedVols = false;
365 rctx.do_not_wait = false;
366 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
371 unbash_spaces(dir->msg);
372 pm_strcpy(jcr->errmsg, dir->msg);
373 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
375 Jmsg(jcr, M_FATAL, 0, _("\n"
376 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
377 dev_name.c_str(), media_type.c_str());
378 bnet_fsend(dir, NO_device, dev_name.c_str());
380 for (error=(char*)rctx->errors.first(); error;
381 error=(char*)rctx->errors.next()) {
382 Jmsg(jcr, M_INFO, 0, "%s", error);
385 Dmsg1(100, ">dird: %s", dir->msg);
387 unbash_spaces(dir->msg);
388 pm_strcpy(jcr->errmsg, dir->msg);
390 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
392 bnet_fsend(dir, BAD_use, jcr->errmsg);
393 Dmsg1(100, ">dird: %s", dir->msg);
397 foreach_alist(store, jcr->dirstore) {
398 delete store->device;
401 delete jcr->dirstore;
403 for (error=(char*)rctx->errors.first(); error;
404 error=(char*)rctx->errors.next()) {
413 * Search for a device suitable for this job.
415 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
423 init_jcr_device_wait_timers(jcr);
425 int can_wait = false;
428 foreach_alist(store, jcr->dirstore) {
430 foreach_alist(device_name, store->device) {
432 rctx.device_name = device_name;
433 stat = search_res_for_device(rctx);
434 if (stat == 1) { /* found available device */
437 } else if (stat == 0) { /* device busy */
440 /* otherwise error */
441 // rctx->errors.push(bstrdup(jcr->errmsg));
449 * We did not find a suitable device, so
450 * if there is some device for which we can wait, then
451 * wait and try again until the wait time expires
453 if (rctx.do_not_wait || !can_wait || !wait_for_device(jcr, first)) {
456 first = false; /* first wait complete */
459 for (error=(char*)rctx->errors.first(); error;
460 error=(char*)rctx->errors.next()) {
472 * Search for a particular storage device with particular storage
473 * characteristics (MediaType).
475 static int search_res_for_device(RCTX &rctx)
477 AUTOCHANGER *changer;
478 BSOCK *dir = rctx.jcr->dir_bsock;
482 Dmsg1(100, "Search res for %s\n", rctx.device_name);
483 if (!rctx.available_autochanger) {
484 foreach_res(rctx.device, R_DEVICE) {
485 Dmsg1(100, "Try res=%s\n", rctx.device->hdr.name);
486 /* Find resource, and make sure we were able to open it */
487 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
488 stat = reserve_device(rctx);
492 Dmsg1(220, "Got: %s", dir->msg);
493 bash_spaces(rctx.device_name);
494 ok = bnet_fsend(dir, OK_device, rctx.device_name);
495 Dmsg1(100, ">dird dev: %s", dir->msg);
500 foreach_res(changer, R_AUTOCHANGER) {
501 Dmsg1(100, "Try changer res=%s\n", changer->hdr.name);
502 /* Find resource, and make sure we were able to open it */
503 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
504 /* Try each device in this AutoChanger */
505 foreach_alist(rctx.device, changer->device) {
506 Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
507 stat = reserve_device(rctx);
508 if (stat == -1) { /* hard error */
511 if (stat == 0) { /* must wait, try next one */
515 Dmsg1(100, "Device %s opened.\n", rctx.device_name);
516 pm_strcpy(dev_name, rctx.device->hdr.name);
517 bash_spaces(dev_name);
518 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
519 Dmsg1(100, ">dird changer: %s", dir->msg);
524 return 0; /* nothing found */
528 * Try to reserve a specific device.
530 * Returns: 1 -- OK, have DCR
534 static int reserve_device(RCTX &rctx)
538 const int name_len = MAX_NAME_LENGTH;
540 /* Make sure MediaType is OK */
541 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
545 if (!rctx.device->dev) {
546 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
548 if (!rctx.device->dev) {
549 if (rctx.device->changer_res) {
550 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
551 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
552 rctx.device->hdr.name, rctx.device_name);
554 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
555 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
558 return -1; /* no use waiting */
560 Dmsg1(100, "Found device %s\n", rctx.device->hdr.name);
561 dcr = new_dcr(rctx.jcr, rctx.device->dev);
563 BSOCK *dir = rctx.jcr->dir_bsock;
564 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
565 Dmsg1(100, ">dird: %s", dir->msg);
569 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
570 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
571 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
572 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
573 if (rctx.store->append == SD_APPEND) {
574 if (rctx.exact_match && !rctx.have_volume) {
575 dcr->any_volume = true;
576 if (dir_find_next_appendable_volume(dcr)) {
577 Dmsg1(200, "Looking for Volume=%s\n", dcr->VolumeName);
578 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
579 rctx.have_volume = true;
581 Dmsg0(200, "No next volume found\n");
582 rctx.VolumeName[0] = 0;
585 ok = reserve_device_for_append(dcr, rctx);
586 Dmsg3(200, "dev_name=%s mediatype=%s ok=%d\n", dcr->dev_name, dcr->media_type, ok);
588 ok = reserve_device_for_read(dcr);
591 free_dcr(rctx.jcr->dcr);
598 * We "reserve" the drive by setting the ST_READ bit. No one else
599 * should touch the drive until that is cleared.
600 * This allows the DIR to "reserve" the device before actually
603 static bool reserve_device_for_read(DCR *dcr)
605 DEVICE *dev = dcr->dev;
611 dev->block(BST_DOING_ACQUIRE);
613 if (is_device_unmounted(dev)) {
614 Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
615 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
620 if (dev->is_busy()) {
621 Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
622 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
623 Mmsg1(jcr->errmsg, _("Device %s is busy.\n"),
639 * We reserve the device for appending by incrementing the
640 * reserved_device. We do virtually all the same work that
641 * is done in acquire_device_for_append(), but we do
642 * not attempt to mount the device. This routine allows
643 * the DIR to reserve multiple devices before *really*
644 * starting the job. It also permits the SD to refuse
645 * certain devices (not up, ...).
647 * Note, in reserving a device, if the device is for the
648 * same pool and the same pool type, then it is acceptable.
649 * The Media Type has already been checked. If we are
650 * the first tor reserve the device, we put the pool
651 * name and pool type in the device record.
653 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
656 DEVICE *dev = dcr->dev;
661 dev->block(BST_DOING_ACQUIRE);
663 if (dev->can_read()) {
664 Mmsg1(jcr->errmsg, _("Device %s is busy reading.\n"), dev->print_name());
665 Dmsg1(100, "%s", jcr->errmsg);
669 if (is_device_unmounted(dev)) {
670 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"), dev->print_name());
671 Dmsg1(100, "%s", jcr->errmsg);
675 Dmsg1(190, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
677 if (can_reserve_drive(dcr, rctx) != 1) {
678 Mmsg1(jcr->errmsg, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
679 Dmsg1(100, "%s", jcr->errmsg);
683 dev->reserved_device++;
684 Dmsg1(200, "Inc reserve=%d\n", dev->reserved_device);
685 dcr->reserved_device = true;
694 * Returns: 1 if drive can be reserved
695 * 0 if we should wait
698 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
700 DEVICE *dev = dcr->dev;
703 /* Check for prefer mounted volumes */
704 if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
705 Dmsg0(200, "want mounted -- no vol\n");
706 return 0; /* No volume mounted */
709 /* Check for exact Volume name match */
710 if (rctx.exact_match && rctx.have_volume &&
711 strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
712 Dmsg2(200, "Not exact match have=%s want=%s\n",
713 dev->VolHdr.VolumeName, rctx.VolumeName);
717 /* Check for unused autochanger drive */
718 if (rctx.available_autochanger && dev->num_writers == 0 &&
719 dev->VolHdr.VolumeName[0] == 0) {
720 /* Device is available but not yet reserved, reserve it for us */
721 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
722 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
723 return 1; /* reserve drive */
727 * Handle the case that there are no writers
729 if (dev->num_writers == 0) {
730 /* Now check if there are any reservations on the drive */
731 if (dev->reserved_device) {
732 /* Now check if we want the same Pool and pool type */
733 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
734 strcmp(dev->pool_type, dcr->pool_type) == 0) {
735 /* OK, compatible device */
736 Dmsg0(200, "got dev: num_writers=0, reserved, pool matches\n");
739 /* Drive not suitable for us */
740 Dmsg2(200, "busy: num_writers=0, reserved, pool=%s wanted=%s\n",
741 dev->pool_name, dcr->pool_name);
744 } else if (dev->can_append()) {
745 /* Device in append mode, check if changing pool */
746 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
747 strcmp(dev->pool_type, dcr->pool_type) == 0) {
748 Dmsg0(200, "got dev: num_writers=0, can_append, pool matches\n");
749 /* OK, compatible device */
752 /* Changing pool, unload old tape if any in drive */
753 Dmsg0(200, "got dev: num_writers=0, reserved, pool change\n");
754 unload_autochanger(dcr, 0);
757 /* Device is available but not yet reserved, reserve it for us */
758 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
759 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
760 return 1; /* reserve drive */
764 * Check if the device is in append mode with writers (i.e.
765 * available if pool is the same).
767 if (dev->can_append() || dev->num_writers > 0) {
768 Dmsg0(190, "device already in append.\n");
769 /* Yes, now check if we want the same Pool and pool type */
770 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
771 strcmp(dev->pool_type, dcr->pool_type) == 0) {
772 Dmsg0(200, "got dev: num_writers>=0, can_append, pool matches\n");
773 /* OK, compatible device */
776 /* Drive not suitable for us */
777 Jmsg(jcr, M_WARNING, 0, _("Wanted Pool \"%s\", but device %s is using Pool \"%s\" .\n"),
778 dcr->pool_name, dev->print_name(), dev->pool_name);
779 Dmsg2(200, "busy: num_writers>0, can_append, pool=%s wanted=%s\n",
780 dev->pool_name, dcr->pool_name);
784 Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
785 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
786 return -1; /* error, should not get here */