2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Drive reservation functions for Storage Daemon
33 * Split from job.c and acquire.c June 2005
42 const int dbglvl = 150;
44 static brwlock_t reservation_lock;
46 /* Forward referenced functions */
47 static int can_reserve_drive(DCR *dcr, RCTX &rctx);
48 static int reserve_device(RCTX &rctx);
49 static bool reserve_device_for_read(DCR *dcr);
50 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
51 static bool use_storage_cmd(JCR *jcr);
52 static void queue_reserve_message(JCR *jcr);
53 static void pop_reserve_messages(JCR *jcr);
54 //void switch_device(DCR *dcr, DEVICE *dev);
56 /* Requests from the Director daemon */
57 static char use_storage[] = "use storage=%127s media_type=%127s "
58 "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
59 static char use_device[] = "use device=%127s\n";
61 /* Responses sent to Director daemon */
62 static char OK_device[] = "3000 OK use device device=%s\n";
63 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
64 static char BAD_use[] = "3913 Bad use command: %s\n";
66 bool use_cmd(JCR *jcr)
69 * Get the device, media, and pool information
71 if (!use_storage_cmd(jcr)) {
72 set_jcr_job_status(jcr, JS_ErrorTerminated);
73 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
80 * This allows a given thread to recursively call lock_reservations.
81 * It must, of course, call unlock_... the same number of times.
83 void init_reservations_lock()
86 if ((errstat=rwl_init(&reservation_lock)) != 0) {
88 Emsg1(M_ABORT, 0, _("Unable to initialize reservation lock. ERR=%s\n"),
89 be.bstrerror(errstat));
95 void term_reservations_lock()
97 rwl_destroy(&reservation_lock);
101 int reservations_lock_count = 0;
103 /* This applies to a drive and to Volumes */
104 void _lock_reservations()
107 reservations_lock_count++;
108 if ((errstat=rwl_writelock(&reservation_lock)) != 0) {
110 Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
111 errstat, be.bstrerror(errstat));
115 void _unlock_reservations()
118 reservations_lock_count--;
119 if ((errstat=rwl_writeunlock(&reservation_lock)) != 0) {
121 Emsg2(M_ABORT, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
122 errstat, be.bstrerror(errstat));
126 void DCR::set_reserved()
129 Dmsg2(dbglvl, "Inc reserve=%d dev=%s\n", dev->num_reserved(), dev->print_name());
133 void DCR::clear_reserved()
138 Dmsg2(dbglvl, "Dec reserve=%d dev=%s\n", dev->num_reserved(), dev->print_name());
143 * Remove any reservation from a drive and tell the system
144 * that the volume is unused at least by us.
146 void DCR::unreserve_device()
151 reserved_volume = false;
152 /* If we set read mode in reserving, remove it */
153 if (dev->can_read()) {
156 if (dev->num_writers < 0) {
157 Jmsg1(jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
158 dev->num_writers = 0;
160 if (dev->num_reserved() == 0 && dev->num_writers == 0) {
168 * We get the following type of information:
170 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
174 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
178 static bool use_storage_cmd(JCR *jcr)
180 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
181 BSOCK *dir = jcr->dir_bsock;
189 memset(&rctx, 0, sizeof(RCTX));
192 * If there are multiple devices, the director sends us
193 * use_device for each device that it wants to use.
195 dirstore = New(alist(10, not_owned_by_alist));
196 jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
198 Dmsg1(dbglvl, "<dird: %s", dir->msg);
199 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
200 media_type.c_str(), pool_name.c_str(),
201 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
206 jcr->write_store = dirstore;
208 jcr->read_store = dirstore;
210 rctx.append = append;
211 unbash_spaces(store_name);
212 unbash_spaces(media_type);
213 unbash_spaces(pool_name);
214 unbash_spaces(pool_type);
215 store = new DIRSTORE;
216 dirstore->append(store);
217 memset(store, 0, sizeof(DIRSTORE));
218 store->device = New(alist(10));
219 bstrncpy(store->name, store_name, sizeof(store->name));
220 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
221 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
222 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
223 store->append = append;
225 /* Now get all devices */
226 while (dir->recv() >= 0) {
227 Dmsg1(dbglvl, "<dird device: %s", dir->msg);
228 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
232 unbash_spaces(dev_name);
233 store->device->append(bstrdup(dev_name.c_str()));
235 } while (ok && dir->recv() >= 0);
237 /* Developer debug code */
239 if (debug_level >= dbglvl) {
240 foreach_alist(store, dirstore) {
241 Dmsg5(dbglvl, "Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n",
242 store->name, store->media_type, store->pool_name,
243 store->pool_type, store->append);
244 foreach_alist(device_name, store->device) {
245 Dmsg1(dbglvl, " Device=%s\n", device_name);
250 init_jcr_device_wait_timers(jcr);
251 jcr->dcr = new_dcr(jcr, NULL, NULL); /* get a dcr */
253 BSOCK *dir = jcr->dir_bsock;
254 dir->fsend(_("3939 Could not get dcr\n"));
255 Dmsg1(dbglvl, ">dird: %s", dir->msg);
259 * At this point, we have a list of all the Director's Storage
260 * resources indicated for this Job, which include Pool, PoolType,
261 * storage name, and Media type.
262 * Then for each of the Storage resources, we have a list of
263 * device names that were given.
265 * Wiffle through them and find one that can do the backup.
268 int wait_for_device_retries = 0;
271 rctx.notify_dir = true;
274 for ( ; !fail && !job_canceled(jcr); ) {
275 pop_reserve_messages(jcr);
276 rctx.suitable_device = false;
277 rctx.have_volume = false;
278 rctx.VolumeName[0] = 0;
279 rctx.any_drive = false;
280 if (!jcr->PreferMountedVols) {
282 * Here we try to find a drive that is not used.
283 * This will maximize the use of available drives.
286 rctx.num_writers = 20000000; /* start with impossible number */
287 rctx.low_use_drive = NULL;
288 rctx.PreferMountedVols = false;
289 rctx.exact_match = false;
290 rctx.autochanger_only = true;
291 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
294 /* Look through all drives possibly for low_use drive */
295 if (rctx.low_use_drive) {
296 rctx.try_low_use_drive = true;
297 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
300 rctx.try_low_use_drive = false;
302 rctx.autochanger_only = false;
303 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
308 * Now we look for a drive that may or may not be in
311 /* Look for an exact Volume match all drives */
312 rctx.PreferMountedVols = true;
313 rctx.exact_match = true;
314 rctx.autochanger_only = false;
315 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
318 /* Look for any mounted drive */
319 rctx.exact_match = false;
320 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
324 rctx.any_drive = true;
325 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
328 /* Keep reservations locked *except* during wait_for_device() */
329 unlock_reservations();
331 * The idea of looping on repeat a few times it to ensure
332 * that if there is some subtle timing problem between two
333 * jobs, we will simply try again, and most likely succeed.
334 * This can happen if one job reserves a drive or finishes using
335 * a drive at the same time a second job wants it.
337 if (repeat++ > 1) { /* try algorithm 3 times */
338 bmicrosleep(30, 0); /* wait a bit */
339 Dmsg0(dbglvl, "repeat reserve algorithm\n");
340 } else if (!rctx.suitable_device || !wait_for_device(jcr, wait_for_device_retries)) {
341 Dmsg0(dbglvl, "Fail. !suitable_device || !wait_for_device\n");
345 dir->signal(BNET_HEARTBEAT); /* Inform Dir that we are alive */
347 unlock_reservations();
350 * If we get here, there are no suitable devices available, which
351 * means nothing configured. If a device is suitable but busy
352 * with another Volume, we will not come here.
354 unbash_spaces(dir->msg);
355 pm_strcpy(jcr->errmsg, dir->msg);
356 Jmsg(jcr, M_FATAL, 0, _("Device reservation failed for JobId=%d: %s\n"),
357 jcr->JobId, jcr->errmsg);
358 dir->fsend(NO_device, dev_name.c_str());
360 Dmsg1(dbglvl, ">dird: %s", dir->msg);
363 unbash_spaces(dir->msg);
364 pm_strcpy(jcr->errmsg, dir->msg);
365 Jmsg(jcr, M_FATAL, 0, _("Failed command: %s\n"), jcr->errmsg);
366 dir->fsend(BAD_use, jcr->errmsg);
367 Dmsg1(dbglvl, ">dird: %s", dir->msg);
370 release_reserve_messages(jcr);
376 * Walk through the autochanger resources and check if
377 * the volume is in one of them.
379 * Returns: true if volume is in device
382 static bool is_vol_in_autochanger(RCTX &rctx, VOLRES *vol)
384 AUTOCHANGER *changer = vol->dev->device->changer_res;
386 /* Find resource, and make sure we were able to open it */
387 if (strcmp(rctx.device_name, changer->hdr.name) == 0) {
388 Dmsg1(dbglvl, "Found changer device %s\n", vol->dev->device->hdr.name);
391 Dmsg1(dbglvl, "Incorrect changer device %s\n", changer->hdr.name);
396 * Search for a device suitable for this job.
397 * Note, this routine sets sets rctx.suitable_device if any
398 * device exists within the SD. The device may not be actually
400 * It also returns if it finds a useable device.
402 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
411 dirstore = jcr->write_store;
413 dirstore = jcr->read_store;
415 Dmsg5(dbglvl, "Start find_suit_dev PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
416 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
417 rctx.autochanger_only, rctx.any_drive);
420 * If the appropriate conditions of this if are met, namely that
421 * we are appending and the user wants mounted drive (or we
422 * force try a mounted drive because they are all busy), we
423 * start by looking at all the Volumes in the volume list.
425 if (!is_vol_list_empty() && rctx.append && rctx.PreferMountedVols) {
426 dlist *temp_vol_list;
428 temp_vol_list = dup_vol_list(jcr);
430 /* Look through reserved volumes for one we can use */
431 Dmsg0(dbglvl, "look for vol in vol list\n");
432 foreach_dlist(vol, temp_vol_list) {
434 Dmsg1(dbglvl, "vol=%s no dev\n", vol->vol_name);
437 /* Check with Director if this Volume is OK */
438 bstrncpy(dcr->VolumeName, vol->vol_name, sizeof(dcr->VolumeName));
439 if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) {
443 Dmsg1(dbglvl, "vol=%s OK for this job\n", vol->vol_name);
444 foreach_alist(store, dirstore) {
447 foreach_alist(device_name, store->device) {
448 /* Found a device, try to use it */
449 rctx.device_name = device_name;
450 rctx.device = vol->dev->device;
452 if (vol->dev->is_autochanger()) {
453 Dmsg1(dbglvl, "vol=%s is in changer\n", vol->vol_name);
454 if (!is_vol_in_autochanger(rctx, vol)) {
457 } else if (strcmp(device_name, vol->dev->device->hdr.name) != 0) {
458 Dmsg2(dbglvl, "device=%s not suitable want %s\n",
459 vol->dev->device->hdr.name, device_name);
463 bstrncpy(rctx.VolumeName, vol->vol_name, sizeof(rctx.VolumeName));
464 rctx.have_volume = true;
465 /* Try reserving this device and volume */
466 Dmsg2(dbglvl, "try vol=%s on device=%s\n", rctx.VolumeName, device_name);
467 stat = reserve_device(rctx);
468 if (stat == 1) { /* found available device */
469 Dmsg1(dbglvl, "Suitable device found=%s\n", device_name);
472 } else if (stat == 0) { /* device busy */
473 Dmsg1(dbglvl, "Suitable device=%s, busy: not use\n", device_name);
475 /* otherwise error */
476 Dmsg0(dbglvl, "No suitable device found.\n");
478 rctx.have_volume = false;
479 rctx.VolumeName[0] = 0;
488 } /* end for loop over reserved volumes */
490 Dmsg0(dbglvl, "lock volumes\n");
491 free_temp_vol_list(temp_vol_list);
494 Dmsg1(dbglvl, "OK dev found. Vol=%s from in-use vols list\n", rctx.VolumeName);
499 * No reserved volume we can use, so now search for an available device.
501 * For each storage device that the user specified, we
502 * search and see if there is a resource for that device.
504 foreach_alist(store, dirstore) {
506 foreach_alist(device_name, store->device) {
508 rctx.device_name = device_name;
509 stat = search_res_for_device(rctx);
510 if (stat == 1) { /* found available device */
511 Dmsg1(dbglvl, "available device found=%s\n", device_name);
514 } else if (stat == 0) { /* device busy */
515 Dmsg1(dbglvl, "No usable device=%s, busy: not use\n", device_name);
517 /* otherwise error */
518 Dmsg0(dbglvl, "No usable device found.\n");
526 Dmsg1(dbglvl, "OK dev found. Vol=%s\n", rctx.VolumeName);
528 Dmsg0(dbglvl, "Leave find_suit_dev: no dev found.\n");
534 * Search for a particular storage device with particular storage
535 * characteristics (MediaType).
537 int search_res_for_device(RCTX &rctx)
539 AUTOCHANGER *changer;
542 Dmsg1(dbglvl, "search res for %s\n", rctx.device_name);
543 /* Look through Autochangers first */
544 foreach_res(changer, R_AUTOCHANGER) {
545 Dmsg1(dbglvl, "Try match changer res=%s\n", changer->hdr.name);
546 /* Find resource, and make sure we were able to open it */
547 if (strcmp(rctx.device_name, changer->hdr.name) == 0) {
548 /* Try each device in this AutoChanger */
549 foreach_alist(rctx.device, changer->device) {
550 Dmsg1(dbglvl, "Try changer device %s\n", rctx.device->hdr.name);
551 if (!rctx.device->autoselect) {
552 Dmsg1(100, "Device %s not autoselect skipped.\n",
553 rctx.device->hdr.name);
554 continue; /* device is not available */
556 stat = reserve_device(rctx);
557 if (stat != 1) { /* try another device */
561 if (rctx.store->append == SD_APPEND) {
562 Dmsg2(dbglvl, "Device %s reserved=%d for append.\n",
563 rctx.device->hdr.name, rctx.jcr->dcr->dev->num_reserved());
565 Dmsg2(dbglvl, "Device %s reserved=%d for read.\n",
566 rctx.device->hdr.name, rctx.jcr->read_dcr->dev->num_reserved());
573 /* Now if requested look through regular devices */
574 if (!rctx.autochanger_only) {
575 foreach_res(rctx.device, R_DEVICE) {
576 Dmsg1(dbglvl, "Try match res=%s\n", rctx.device->hdr.name);
577 /* Find resource, and make sure we were able to open it */
578 if (strcmp(rctx.device_name, rctx.device->hdr.name) == 0) {
579 stat = reserve_device(rctx);
580 if (stat != 1) { /* try another device */
584 if (rctx.store->append == SD_APPEND) {
585 Dmsg2(dbglvl, "Device %s reserved=%d for append.\n",
586 rctx.device->hdr.name, rctx.jcr->dcr->dev->num_reserved());
588 Dmsg2(dbglvl, "Device %s reserved=%d for read.\n",
589 rctx.device->hdr.name, rctx.jcr->read_dcr->dev->num_reserved());
595 return -1; /* nothing found */
599 * Try to reserve a specific device.
601 * Returns: 1 -- OK, have DCR
605 static int reserve_device(RCTX &rctx)
609 const int name_len = MAX_NAME_LENGTH;
611 /* Make sure MediaType is OK */
612 Dmsg2(dbglvl, "chk MediaType device=%s request=%s\n",
613 rctx.device->media_type, rctx.store->media_type);
614 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
618 /* Make sure device exists -- i.e. we can stat() it */
619 if (!rctx.device->dev) {
620 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
622 if (!rctx.device->dev) {
623 if (rctx.device->changer_res) {
624 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
625 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
626 rctx.device->hdr.name, rctx.device_name);
628 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
629 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
632 return -1; /* no use waiting */
635 rctx.suitable_device = true;
636 Dmsg1(dbglvl, "try reserve %s\n", rctx.device->hdr.name);
637 if (rctx.store->append) {
638 dcr = new_dcr(rctx.jcr, rctx.jcr->dcr, rctx.device->dev);
640 dcr = new_dcr(rctx.jcr, rctx.jcr->read_dcr, rctx.device->dev);
643 BSOCK *dir = rctx.jcr->dir_bsock;
644 dir->fsend(_("3926 Could not get dcr for device: %s\n"), rctx.device_name);
645 Dmsg1(dbglvl, ">dird: %s", dir->msg);
648 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
649 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
650 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
651 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
652 if (rctx.store->append == SD_APPEND) {
653 Dmsg2(dbglvl, "call reserve for append: have_vol=%d vol=%s\n", rctx.have_volume, rctx.VolumeName);
654 ok = reserve_device_for_append(dcr, rctx);
660 Dmsg5(dbglvl, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
661 dcr->dev->num_reserved(),
662 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
663 Dmsg3(dbglvl, "Vol=%s num_writers=%d, have_vol=%d\n",
664 rctx.VolumeName, dcr->dev->num_writers, rctx.have_volume);
665 if (rctx.have_volume) {
666 Dmsg0(dbglvl, "Call reserve_volume\n");
667 if (reserve_volume(dcr, rctx.VolumeName)) {
668 Dmsg1(dbglvl, "Reserved vol=%s\n", rctx.VolumeName);
670 Dmsg1(dbglvl, "Could not reserve vol=%s\n", rctx.VolumeName);
674 dcr->any_volume = true;
675 Dmsg0(dbglvl, "no vol, call find_next_appendable_vol.\n");
676 if (dir_find_next_appendable_volume(dcr)) {
677 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
678 rctx.have_volume = true;
679 Dmsg1(dbglvl, "looking for Volume=%s\n", rctx.VolumeName);
681 Dmsg0(dbglvl, "No next volume found\n");
682 rctx.have_volume = false;
683 rctx.VolumeName[0] = 0;
685 * If there is at least one volume that is valid and in use,
686 * but we get here, check if we are running with prefers
687 * non-mounted drives. In that case, we have selected a
688 * non-used drive and our one and only volume is mounted
689 * elsewhere, so we bail out and retry using that drive.
691 if (dcr->found_in_use() && !rctx.PreferMountedVols) {
692 rctx.PreferMountedVols = true;
693 if (dcr->VolumeName[0]) {
694 dcr->unreserve_device();
699 * Note. Under some circumstances, the Director can hand us
700 * a Volume name that is not the same as the one on the current
701 * drive, and in that case, the call above to find the next
702 * volume will fail because in attempting to reserve the Volume
703 * the code will realize that we already have a tape mounted,
704 * and it will fail. This *should* only happen if there are
705 * writers, thus the following test. In that case, we simply
706 * bail out, and continue waiting, rather than plunging on
707 * and hoping that the operator can resolve the problem.
709 if (dcr->dev->num_writers != 0) {
710 if (dcr->VolumeName[0]) {
711 dcr->unreserve_device();
718 ok = reserve_device_for_read(dcr);
720 rctx.jcr->read_dcr = dcr;
721 Dmsg5(dbglvl, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
722 dcr->dev->num_reserved(),
723 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
730 if (rctx.notify_dir) {
732 BSOCK *dir = rctx.jcr->dir_bsock;
733 pm_strcpy(dev_name, rctx.device->hdr.name);
734 bash_spaces(dev_name);
735 ok = dir->fsend(OK_device, dev_name.c_str()); /* Return real device name */
736 Dmsg1(dbglvl, ">dird: %s", dir->msg);
743 rctx.have_volume = false;
744 rctx.VolumeName[0] = 0;
745 Dmsg0(dbglvl, "Not OK.\n");
750 * We "reserve" the drive by setting the ST_READ bit. No one else
751 * should touch the drive until that is cleared.
752 * This allows the DIR to "reserve" the device before actually
755 static bool reserve_device_for_read(DCR *dcr)
757 DEVICE *dev = dcr->dev;
762 if (job_canceled(jcr)) {
768 if (dev->is_device_unmounted()) {
769 Dmsg1(dbglvl, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
770 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
771 jcr->JobId, dev->print_name());
772 queue_reserve_message(jcr);
776 if (dev->is_busy()) {
777 Dmsg4(dbglvl, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n",
779 dev->state & ST_READ?1:0, dev->num_writers, dev->num_reserved());
780 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
781 jcr->JobId, dev->print_name());
782 queue_reserve_message(jcr);
798 * We reserve the device for appending by incrementing
799 * num_reserved(). We do virtually all the same work that
800 * is done in acquire_device_for_append(), but we do
801 * not attempt to mount the device. This routine allows
802 * the DIR to reserve multiple devices before *really*
803 * starting the job. It also permits the SD to refuse
804 * certain devices (not up, ...).
806 * Note, in reserving a device, if the device is for the
807 * same pool and the same pool type, then it is acceptable.
808 * The Media Type has already been checked. If we are
809 * the first tor reserve the device, we put the pool
810 * name and pool type in the device record.
812 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
815 DEVICE *dev = dcr->dev;
819 if (job_canceled(jcr)) {
825 /* If device is being read, we cannot write it */
826 if (dev->can_read()) {
827 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
828 jcr->JobId, dev->print_name());
829 Dmsg1(dbglvl, "%s", jcr->errmsg);
830 queue_reserve_message(jcr);
834 /* If device is unmounted, we are out of luck */
835 if (dev->is_device_unmounted()) {
836 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
837 jcr->JobId, dev->print_name());
838 Dmsg1(dbglvl, "%s", jcr->errmsg);
839 queue_reserve_message(jcr);
843 Dmsg1(dbglvl, "reserve_append device is %s\n", dev->print_name());
845 /* Now do detailed tests ... */
846 if (can_reserve_drive(dcr, rctx) != 1) {
847 Dmsg0(dbglvl, "can_reserve_drive!=1\n");
859 static int is_pool_ok(DCR *dcr)
861 DEVICE *dev = dcr->dev;
864 /* Now check if we want the same Pool and pool type */
865 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
866 strcmp(dev->pool_type, dcr->pool_type) == 0) {
867 /* OK, compatible device */
868 Dmsg1(dbglvl, "OK dev: %s num_writers=0, reserved, pool matches\n", dev->print_name());
871 /* Drive Pool not suitable for us */
873 "3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"),
874 (uint32_t)jcr->JobId, dcr->pool_name, dev->pool_name,
875 dev->num_reserved(), dev->print_name());
876 queue_reserve_message(jcr);
877 Dmsg2(dbglvl, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
878 dev->pool_name, dcr->pool_name);
883 static bool is_max_jobs_ok(DCR *dcr)
885 DEVICE *dev = dcr->dev;
888 Dmsg5(dbglvl, "MaxJobs=%d Jobs=%d reserves=%d Status=%s Vol=%s\n",
889 dcr->VolCatInfo.VolCatMaxJobs,
890 dcr->VolCatInfo.VolCatJobs, dev->num_reserved(),
891 dcr->VolCatInfo.VolCatStatus,
893 /* Limit max concurrent jobs on this drive */
894 if (dev->max_concurrent_jobs > 0 && dev->max_concurrent_jobs <=
895 (uint32_t)(dev->num_writers + dev->num_reserved())) {
896 /* Max Concurrent Jobs depassed or already reserved */
897 Mmsg(jcr->errmsg, _("3609 JobId=%u Max concurrent jobs exceeded on drive %s.\n"),
898 (uint32_t)jcr->JobId, dev->print_name());
899 queue_reserve_message(jcr);
900 Dmsg1(dbglvl, "reserve dev failed: %s", jcr->errmsg);
903 if (strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0) {
906 if (dcr->VolCatInfo.VolCatMaxJobs > 0 && dcr->VolCatInfo.VolCatMaxJobs <=
907 (dcr->VolCatInfo.VolCatJobs + dev->num_reserved())) {
908 /* Max Job Vols depassed or already reserved */
909 Mmsg(jcr->errmsg, _("3610 JobId=%u Volume max jobs exceeded on drive %s.\n"),
910 (uint32_t)jcr->JobId, dev->print_name());
911 queue_reserve_message(jcr);
912 Dmsg1(dbglvl, "reserve dev failed: %s", jcr->errmsg);
913 return false; /* wait */
919 * Returns: 1 if drive can be reserved
920 * 0 if we should wait
921 * -1 on error or impossibility
923 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
925 DEVICE *dev = dcr->dev;
928 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
929 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
930 rctx.autochanger_only, rctx.any_drive);
932 /* Check for max jobs on this Volume */
933 if (!is_max_jobs_ok(dcr)) {
937 /* setting any_drive overrides PreferMountedVols flag */
938 if (!rctx.any_drive) {
940 * When PreferMountedVols is set, we keep track of the
941 * drive in use that has the least number of writers, then if
942 * no unmounted drive is found, we try that drive. This
943 * helps spread the load to the least used drives.
945 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
946 Dmsg2(dbglvl, "OK dev=%s == low_drive=%s.\n",
947 dev->print_name(), rctx.low_use_drive->print_name());
950 /* If he wants a free drive, but this one is busy, no go */
951 if (!rctx.PreferMountedVols && dev->is_busy()) {
952 /* Save least used drive */
953 if ((dev->num_writers + dev->num_reserved()) < rctx.num_writers) {
954 rctx.num_writers = dev->num_writers + dev->num_reserved();
955 rctx.low_use_drive = dev;
956 Dmsg2(dbglvl, "set low use drive=%s num_writers=%d\n",
957 dev->print_name(), rctx.num_writers);
959 Dmsg1(dbglvl, "not low use num_writers=%d\n", dev->num_writers+dev->num_reserved());
961 Dmsg0(dbglvl, "failed: !prefMnt && busy.\n");
962 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
963 jcr->JobId, dev->print_name());
964 queue_reserve_message(jcr);
968 /* Check for prefer mounted volumes */
969 if (rctx.PreferMountedVols && !dev->vol && dev->is_tape()) {
970 Mmsg(jcr->errmsg, _("3606 JobId=%u prefers mounted drives, but drive %s has no Volume.\n"),
971 jcr->JobId, dev->print_name());
972 queue_reserve_message(jcr);
973 Dmsg0(dbglvl, "failed: want mounted -- no vol\n");
974 return 0; /* No volume mounted */
977 /* Check for exact Volume name match */
978 /* ***FIXME*** for Disk, we can accept any volume that goes with this
981 if (rctx.exact_match && rctx.have_volume) {
983 Dmsg5(dbglvl, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
984 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
985 rctx.autochanger_only, rctx.any_drive);
986 Dmsg4(dbglvl, "have_vol=%d have=%s resvol=%s want=%s\n",
987 rctx.have_volume, dev->VolHdr.VolumeName,
988 dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName);
989 ok = strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) == 0 ||
990 (dev->vol && strcmp(dev->vol->vol_name, rctx.VolumeName) == 0);
992 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
993 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
995 queue_reserve_message(jcr);
996 Dmsg3(dbglvl, "not OK: dev have=%s resvol=%s want=%s\n",
997 dev->VolHdr.VolumeName, dev->vol?dev->vol->vol_name:"*none*", rctx.VolumeName);
1000 if (!dcr->can_i_use_volume()) {
1001 return 0; /* fail if volume on another drive */
1006 /* Check for unused autochanger drive */
1007 if (rctx.autochanger_only && !dev->is_busy() &&
1008 dev->VolHdr.VolumeName[0] == 0) {
1009 /* Device is available but not yet reserved, reserve it for us */
1010 Dmsg1(dbglvl, "OK Res Unused autochanger %s.\n", dev->print_name());
1011 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1012 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1013 return 1; /* reserve drive */
1017 * Handle the case that there are no writers
1019 if (dev->num_writers == 0) {
1020 /* Now check if there are any reservations on the drive */
1021 if (dev->num_reserved()) {
1022 return is_pool_ok(dcr);
1023 } else if (dev->can_append()) {
1024 if (is_pool_ok(dcr)) {
1027 /* Changing pool, unload old tape if any in drive */
1028 Dmsg0(dbglvl, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
1029 /* ***FIXME*** use set_unload() */
1030 unload_autochanger(dcr, -1);
1033 /* Device is available but not yet reserved, reserve it for us */
1034 Dmsg1(dbglvl, "OK Dev avail reserved %s\n", dev->print_name());
1035 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1036 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1037 return 1; /* reserve drive */
1041 * Check if the device is in append mode with writers (i.e.
1042 * available if pool is the same).
1044 if (dev->can_append() || dev->num_writers > 0) {
1045 return is_pool_ok(dcr);
1047 Pmsg1(000, _("Logic error!!!! JobId=%u Should not get here.\n"), (int)jcr->JobId);
1048 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
1049 jcr->JobId, dev->print_name());
1050 queue_reserve_message(jcr);
1051 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
1052 return -1; /* error, should not get here */
1054 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
1055 jcr->JobId, dev->print_name());
1056 queue_reserve_message(jcr);
1057 Dmsg1(dbglvl, "failed: No reserve %s\n", dev->print_name());
1065 * Queue a reservation error or failure message for this jcr
1067 static void queue_reserve_message(JCR *jcr)
1075 msgs = jcr->reserve_msgs;
1080 * Look for duplicate message. If found, do
1083 for (i=msgs->size()-1; i >= 0; i--) {
1084 msg = (char *)msgs->get(i);
1088 /* Comparison based on 4 digit message number */
1089 if (strncmp(msg, jcr->errmsg, 4) == 0) {
1093 /* Message unique, so insert it */
1094 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1101 * Send any reservation messages queued for this jcr
1103 void send_drive_reserve_messages(JCR *jcr, void sendit(const char *msg, int len, void *sarg), void *arg)
1110 msgs = jcr->reserve_msgs;
1111 if (!msgs || msgs->size() == 0) {
1114 for (i=msgs->size()-1; i >= 0; i--) {
1115 msg = (char *)msgs->get(i);
1117 sendit(" ", 3, arg);
1118 sendit(msg, strlen(msg), arg);
1129 * Pop and release any reservations messages
1131 static void pop_reserve_messages(JCR *jcr)
1137 msgs = jcr->reserve_msgs;
1141 while ((msg = (char *)msgs->pop())) {
1149 * Also called from acquire.c
1151 void release_reserve_messages(JCR *jcr)
1153 pop_reserve_messages(jcr);
1155 if (!jcr->reserve_msgs) {
1158 delete jcr->reserve_msgs;
1159 jcr->reserve_msgs = NULL;