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 ammended 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];
58 static dlist *vol_list = NULL;
59 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
61 /* Forward referenced functions */
62 static int can_reserve_drive(DCR *dcr);
63 static int search_res_for_device(RCTX &rctx);
64 static int reserve_device(RCTX &rctx);
65 static bool reserve_device_for_read(DCR *dcr);
66 static bool reserve_device_for_append(DCR *dcr);
67 static bool use_storage_cmd(JCR *jcr);
68 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx);
70 /* Requests from the Director daemon */
71 static char use_storage[] = "use storage=%127s media_type=%127s "
72 "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
73 static char use_device[] = "use device=%127s\n";
75 /* Responses sent to Director daemon */
76 static char OK_device[] = "3000 OK use device device=%s\n";
77 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
78 static char BAD_use[] = "3913 Bad use command: %s\n";
80 bool use_cmd(JCR *jcr)
83 * Wait for the device, media, and pool information
85 if (!use_storage_cmd(jcr)) {
86 set_jcr_job_status(jcr, JS_ErrorTerminated);
87 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
93 static int my_compare(void *item1, void *item2)
95 return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
100 * Put a new Volume entry in the Volume list. This
101 * effectively reserves the volume so that it will
102 * not be mounted again.
104 * Return: VOLRES entry on success
105 * NULL if the Volume is already in the list
107 VOLRES *new_volume(const char *VolumeName, DEVICE *dev)
110 vol = (VOLRES *)malloc(sizeof(VOLRES));
111 memset(vol, 0, sizeof(VOLRES));
112 vol->vol_name = bstrdup(VolumeName);
115 nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
129 * Search for a Volume name in the Volume list.
131 * Returns: VOLRES entry on success
132 * NULL if the Volume is not in the list
134 VOLRES *find_volume(const char *VolumeName)
137 vol.vol_name = bstrdup(VolumeName);
139 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
146 * Free a Volume from the Volume list
148 * Returns: true if the Volume found and removed from the list
149 * false if the Volume is not in the list
151 bool free_volume(DEVICE *dev)
155 if (dev->VolHdr.VolName[0] == 0) {
158 vol.vol_name = bstrdup(dev->VolHdr.VolName);
160 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
162 vol_list->remove(fvol);
163 free(fvol->vol_name);
168 dev->VolHdr.VolName[0] = 0;
173 * List Volumes -- this should be moved to status.c
175 void list_volumes(BSOCK *user)
178 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
179 bnet_fsend(user, "%s\n", vol->vol_name);
183 /* Create the Volume list */
184 void create_volume_list()
187 if (vol_list == NULL) {
188 vol_list = New(dlist(dummy, &dummy->link));
192 /* Release all Volumes from the list */
193 void free_volume_list()
196 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
197 Dmsg1(000, "Unreleased Volume=%s\n", vol->vol_name);
203 bool is_volume_in_use(const char *VolumeName)
205 VOLRES *vol = find_volume(VolumeName);
207 return false; /* vol not in list */
209 if (!vol->dev) { /* vol not attached to device */
212 if (!vol->dev->is_busy()) {
219 static bool use_storage_cmd(JCR *jcr)
221 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
222 BSOCK *dir = jcr->dir_bsock;
235 * If there are multiple devices, the director sends us
236 * use_device for each device that it wants to use.
238 Dmsg1(100, "<dird: %s", dir->msg);
239 jcr->dirstore = New(alist(10, not_owned_by_alist));
241 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
242 media_type.c_str(), pool_name.c_str(),
243 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
247 unbash_spaces(store_name);
248 unbash_spaces(media_type);
249 unbash_spaces(pool_name);
250 unbash_spaces(pool_type);
251 store = new DIRSTORE;
252 jcr->dirstore->append(store);
253 memset(store, 0, sizeof(DIRSTORE));
254 store->device = New(alist(10));
255 bstrncpy(store->name, store_name, sizeof(store->name));
256 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
257 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
258 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
259 store->append = append;
261 /* Now get all devices */
262 while (bnet_recv(dir) >= 0) {
263 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
267 unbash_spaces(dev_name);
268 store->device->append(bstrdup(dev_name.c_str()));
270 } while (ok && bnet_recv(dir) >= 0);
273 /* This loop is debug code and can be removed */
274 /* ***FIXME**** remove after 1.38 release */
275 foreach_alist(store, jcr->dirstore) {
276 Dmsg4(100, "Storage=%s media_type=%s pool=%s pool_type=%s\n",
277 store->name, store->media_type, store->pool_name,
279 foreach_alist(device_name, store->device) {
280 Dmsg1(100, " Device=%s\n", device_name);
286 * At this point, we have a list of all the Director's Storage
287 * resources indicated for this Job, which include Pool, PoolType,
288 * storage name, and Media type.
289 * Then for each of the Storage resources, we have a list of
290 * device names that were given.
292 * Wiffle through them and find one that can do the backup.
295 ok = find_suitable_device_for_job(jcr, rctx);
300 unbash_spaces(dir->msg);
301 pm_strcpy(jcr->errmsg, dir->msg);
302 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
304 Jmsg(jcr, M_FATAL, 0, _("\n"
305 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
306 dev_name.c_str(), media_type.c_str());
307 bnet_fsend(dir, NO_device, dev_name.c_str());
309 for (error=(char*)rctx->errors.first(); error;
310 error=(char*)rctx->errors.next()) {
311 Jmsg(jcr, M_INFO, 0, "%s", error);
314 Dmsg1(100, ">dird: %s\n", dir->msg);
316 unbash_spaces(dir->msg);
317 pm_strcpy(jcr->errmsg, dir->msg);
319 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
321 bnet_fsend(dir, BAD_use, jcr->errmsg);
322 Dmsg1(100, ">dird: %s\n", dir->msg);
326 foreach_alist(store, jcr->dirstore) {
327 delete store->device;
330 delete jcr->dirstore;
332 for (error=(char*)rctx->errors.first(); error;
333 error=(char*)rctx->errors.next()) {
342 * Search for a device suitable for this job.
344 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
352 init_jcr_device_wait_timers(jcr);
354 int need_wait = false;
355 foreach_alist(store, jcr->dirstore) {
357 foreach_alist(device_name, store->device) {
359 rctx.device_name = device_name;
360 stat = search_res_for_device(rctx);
361 if (stat == 1) { /* found available device */
365 } else if (stat == 0) { /* device busy */
368 /* otherwise error */
369 // rctx->errors.push(bstrdup(jcr->errmsg));
373 * If there is some device for which we can wait, then
374 * wait and try again until the wait time expires
376 if (!need_wait || !wait_for_device(jcr, first)) {
381 for (error=(char*)rctx->errors.first(); error;
382 error=(char*)rctx->errors.next()) {
395 * Search for a particular storage device with particular storage
396 * characteristics (MediaType).
398 static int search_res_for_device(RCTX &rctx)
400 AUTOCHANGER *changer;
401 BSOCK *dir = rctx.jcr->dir_bsock;
405 Dmsg1(100, "Search res for %s\n", rctx.device_name);
406 foreach_res(rctx.device, R_DEVICE) {
407 Dmsg1(100, "Try res=%s\n", rctx.device->hdr.name);
408 /* Find resource, and make sure we were able to open it */
409 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0 &&
410 strcmp(rctx.device->media_type, rctx.store->media_type) == 0) {
411 stat = reserve_device(rctx);
415 Dmsg1(220, "Got: %s", dir->msg);
416 bash_spaces(rctx.device_name);
417 ok = bnet_fsend(dir, OK_device, rctx.device_name);
418 Dmsg1(100, ">dird: %s\n", dir->msg);
422 foreach_res(changer, R_AUTOCHANGER) {
423 Dmsg1(100, "Try changer res=%s\n", changer->hdr.name);
424 /* Find resource, and make sure we were able to open it */
425 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
426 /* Try each device in this AutoChanger */
427 foreach_alist(rctx.device, changer->device) {
428 Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
429 stat = reserve_device(rctx);
430 if (stat == -1) { /* hard error */
433 if (stat == 0) { /* must wait, try next one */
437 Dmsg1(100, "Device %s opened.\n", rctx.device_name);
438 pm_strcpy(dev_name, rctx.device->hdr.name);
439 bash_spaces(dev_name);
440 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
441 Dmsg1(100, ">dird: %s\n", dir->msg);
446 return 0; /* nothing found */
450 * Try to reserve a specific device.
452 * Returns: 1 -- OK, have DCR
456 static int reserve_device(RCTX &rctx)
460 const int name_len = MAX_NAME_LENGTH;
461 if (!rctx.device->dev) {
462 rctx.device->dev = init_dev(rctx.jcr, NULL, rctx.device);
464 if (!rctx.device->dev) {
465 if (rctx.device->changer_res) {
466 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
467 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
468 rctx.device->hdr.name, rctx.device_name);
470 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
471 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
474 return -1; /* no use waiting */
476 Dmsg1(100, "Found device %s\n", rctx.device->hdr.name);
477 dcr = new_dcr(rctx.jcr, rctx.device->dev);
479 BSOCK *dir = rctx.jcr->dir_bsock;
480 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
481 Dmsg1(100, ">dird: %s\n", dir->msg);
485 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
486 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
487 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
488 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
489 if (rctx.store->append == SD_APPEND) {
490 ok = reserve_device_for_append(dcr);
491 Dmsg3(200, "dev_name=%s mediatype=%s ok=%d\n", dcr->dev_name, dcr->media_type, ok);
493 ok = reserve_device_for_read(dcr);
496 free_dcr(rctx.jcr->dcr);
503 * We "reserve" the drive by setting the ST_READ bit. No one else
504 * should touch the drive until that is cleared.
505 * This allows the DIR to "reserve" the device before actually
508 static bool reserve_device_for_read(DCR *dcr)
510 DEVICE *dev = dcr->dev;
516 dev->block(BST_DOING_ACQUIRE);
518 if (device_is_unmounted(dev)) {
519 Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
520 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
525 if (dev->is_busy()) {
526 Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
527 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
528 Mmsg1(jcr->errmsg, _("Device %s is busy.\n"),
544 * We reserve the device for appending by incrementing the
545 * reserved_device. We do virtually all the same work that
546 * is done in acquire_device_for_append(), but we do
547 * not attempt to mount the device. This routine allows
548 * the DIR to reserve multiple devices before *really*
549 * starting the job. It also permits the SD to refuse
550 * certain devices (not up, ...).
552 * Note, in reserving a device, if the device is for the
553 * same pool and the same pool type, then it is acceptable.
554 * The Media Type has already been checked. If we are
555 * the first tor reserve the device, we put the pool
556 * name and pool type in the device record.
558 static bool reserve_device_for_append(DCR *dcr)
561 DEVICE *dev = dcr->dev;
566 dev->block(BST_DOING_ACQUIRE);
568 if (dev->can_read()) {
569 Mmsg1(jcr->errmsg, _("Device %s is busy reading.\n"), dev->print_name());
573 if (device_is_unmounted(dev)) {
574 Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"), dev->print_name());
578 Dmsg1(190, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
580 if (can_reserve_drive(dcr) != 1) {
581 Mmsg1(jcr->errmsg, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
585 dev->reserved_device++;
586 Dmsg1(200, "============= Inc reserve=%d\n", dev->reserved_device);
587 dcr->reserved_device = true;
596 * Returns: 1 if drive can be reserved
597 * 0 if we should wait
600 static int can_reserve_drive(DCR *dcr)
602 DEVICE *dev = dcr->dev;
605 * First handle the case that the drive is not yet in append mode
607 if (!dev->can_append() && dev->num_writers == 0) {
608 /* Now check if there are any reservations on the drive */
609 if (dev->reserved_device) {
610 /* Yes, now check if we want the same Pool and pool type */
611 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
612 strcmp(dev->pool_type, dcr->pool_type) == 0) {
613 /* OK, compatible device */
615 /* Drive not suitable for us */
619 /* Device is available but not yet reserved, reserve it for us */
620 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
621 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
623 return 1; /* reserve drive */
627 * Check if device in append mode with no writers (i.e. available)
629 if (dev->can_append() && dev->num_writers == 0) {
630 /* Device is available but not yet reserved, reserve it for us */
631 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
632 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
637 * Now check if the device is in append mode with writers (i.e.
638 * available if pool is the same).
640 if (dev->can_append() || dev->num_writers > 0) {
641 Dmsg0(190, "device already in append.\n");
642 /* Yes, now check if we want the same Pool and pool type */
643 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
644 strcmp(dev->pool_type, dcr->pool_type) == 0) {
645 /* OK, compatible device */
647 /* Drive not suitable for us */
648 Jmsg(jcr, M_WARNING, 0, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
652 Pmsg0(000, "Logic error!!!! Should not get here.\n");
653 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
654 return -1; /* error, should not get here */
656 return 1; /* reserve drive */