2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 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 plus additions
11 that are listed in the file LICENSE.
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 John Walker.
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 static dlist *vol_list = NULL;
43 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
45 /* Forward referenced functions */
46 static int can_reserve_drive(DCR *dcr, RCTX &rctx);
47 static int reserve_device(RCTX &rctx);
48 static bool reserve_device_for_read(DCR *dcr);
49 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
50 static bool use_storage_cmd(JCR *jcr);
51 static void queue_reserve_message(JCR *jcr);
53 /* Requests from the Director daemon */
54 static char use_storage[] = "use storage=%127s media_type=%127s "
55 "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
56 static char use_device[] = "use device=%127s\n";
58 /* Responses sent to Director daemon */
59 static char OK_device[] = "3000 OK use device device=%s\n";
60 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
61 static char BAD_use[] = "3913 Bad use command: %s\n";
63 bool use_cmd(JCR *jcr)
66 * Get the device, media, and pool information
68 if (!use_storage_cmd(jcr)) {
69 set_jcr_job_status(jcr, JS_ErrorTerminated);
70 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
76 static int my_compare(void *item1, void *item2)
78 return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
81 static brwlock_t reservation_lock;
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));
94 void term_reservations_lock()
96 rwl_destroy(&reservation_lock);
99 int reservations_lock_count = 0;
101 /* This applies to a drive and to Volumes */
102 void _lock_reservations()
105 reservations_lock_count++;
106 if ((errstat=rwl_writelock(&reservation_lock)) != 0) {
108 Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
109 errstat, be.bstrerror(errstat));
113 void _unlock_reservations()
116 reservations_lock_count--;
117 if ((errstat=rwl_writeunlock(&reservation_lock)) != 0) {
119 Emsg2(M_ABORT, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
120 errstat, be.bstrerror(errstat));
125 * List Volumes -- this should be moved to status.c
132 static void debug_list_volumes(const char *imsg, bool do_lock)
135 POOL_MEM msg(PM_MESSAGE);
139 if (do_lock) P(vol_list_lock);
140 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
142 Mmsg(msg, "List from %s: %s at %p on device %s\n", imsg,
143 vol->vol_name, vol->vol_name, vol->dev->print_name());
145 Mmsg(msg, "List from %s: %s at %p no dev\n", imsg, vol->vol_name, vol->vol_name);
147 Dmsg1(100, "%s", msg.c_str());
151 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
152 if (vol->dev == dev) {
153 Dmsg0(000, "Two Volumes on same device.\n");
159 Dmsg2(100, "List from %s: %d volumes\n", imsg, count);
160 if (do_lock) V(vol_list_lock);
165 * List Volumes -- this should be moved to status.c
167 void list_volumes(void sendit(const char *msg, int len, void *sarg), void *arg)
170 POOL_MEM msg(PM_MESSAGE);
174 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
176 len = Mmsg(msg, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
177 sendit(msg.c_str(), len, arg);
179 len = Mmsg(msg, "%s no dev\n", vol->vol_name);
180 sendit(msg.c_str(), len, arg);
187 * Create a Volume item to put in the Volume list
188 * Ensure that the device points to it.
190 static VOLRES *new_vol_item(DCR *dcr, const char *VolumeName)
193 vol = (VOLRES *)malloc(sizeof(VOLRES));
194 memset(vol, 0, sizeof(VOLRES));
195 vol->vol_name = bstrdup(VolumeName);
197 Dmsg4(100, "New Vol=%s at %p dev=%s JobId=%u\n", VolumeName, vol->vol_name,
198 vol->dev->print_name(), (int)dcr->jcr->JobId);
202 static void free_vol_item(VOLRES *vol)
206 vol->dev->vol = NULL;
213 * Put a new Volume entry in the Volume list. This
214 * effectively reserves the volume so that it will
215 * not be mounted again.
217 * If the device has any current volume associated with it,
218 * and it is a different Volume, and the device is not busy,
219 * we release the old Volume item and insert the new one.
221 * It is assumed that the device is free and locked so that
222 * we can change the device structure.
224 * Some details of the Volume list handling:
226 * 1. The Volume list entry must be attached to the drive (rather than
227 * attached to a job as it currently is. I.e. the drive that "owns"
228 * the volume (reserved, in use, mounted)
229 * must point to the volume (still to be maintained in a list).
231 * 2. The Volume is entered in the list when a drive is reserved.
233 * 3. When a drive is in use, the device code must appropriately update the
234 * volume name as it changes (currently the list is static -- an entry is
235 * removed when the Volume is no longer reserved, in use or mounted).
236 * The new code must keep the same list entry as long as the drive
237 * has any volume associated with it but the volume name in the list
238 * must be updated when the drive has a different volume mounted.
240 * 4. A job that has reserved a volume, can un-reserve the volume, and if the
241 * volume is not mounted, and not reserved, and not in use, it will be
242 * removed from the list.
244 * 5. If a job wants to reserve a drive with a different Volume from the one on
245 * the drive, it can re-use the drive for the new Volume.
247 * 6. If a job wants a Volume that is in a different drive, it can either use the
248 * other drive or take the volume, only if the other drive is not in use or
251 * One nice aspect of this is that the reserve use count and the writer use count
252 * already exist and are correctly programmed and will need no changes -- use
253 * counts are always very tricky.
255 * The old code had a concept of "reserving" a Volume, but it needs to be changed
256 * to reserving and using a drive. A volume is must be attached to (owned by) a
257 * drive and can move from drive to drive or be unused given certain specific
258 * conditions of the drive. The key is that the drive must "own" the Volume.
259 * The old code has the job (dcr) owning the volume (more or less). The job is
260 * to change the insertion and removal of the volumes from the list to be based
261 * on the drive rather than the job. The new logic described above needs to be
262 * reviewed a couple more times for completeness and correctness. Then I can
266 * Return: VOLRES entry on success
267 * NULL volume busy on another drive
269 VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
272 DEVICE *dev = dcr->dev;
276 Dmsg1(100, "reserve_volume %s\n", VolumeName);
278 * We lock the reservations system here to ensure
279 * when adding a new volume that no newly scheduled
280 * job can reserve it.
283 debug_list_volumes("begin reserve_volume", debug_nolock);
285 * First, remove any old volume attached to this device as it
291 * Make sure we don't remove the current volume we are inserting
292 * because it was probably inserted by another job.
294 if (strcmp(vol->vol_name, VolumeName) == 0) {
295 goto get_out; /* Volume already on this device */
297 Dmsg3(100, "reserve_vol free vol=%s at %p JobId=%u\n", vol->vol_name,
298 vol->vol_name, (int)dcr->jcr->JobId);
299 debug_list_volumes("reserve_vol free", debug_nolock);
300 vol_list->remove(vol);
305 /* Create a new Volume entry */
306 nvol = new_vol_item(dcr, VolumeName);
309 * Now try to insert the new Volume
311 vol = (VOLRES *)vol_list->binary_insert(nvol, my_compare);
313 Dmsg2(100, "Found vol=%s dev-same=%d\n", vol->vol_name, dev==vol->dev);
315 * At this point, a Volume with this name already is in the list,
316 * so we simply release our new Volume entry. Note, this should
317 * only happen if we are moving the volume from one drive to another.
319 Dmsg3(100, "reserve_vol free-tmp vol=%s at %p JobId=%u\n", vol->vol_name,
320 vol->vol_name, (int)dcr->jcr->JobId);
322 * Clear dev pointer so that free_vol_item() doesn't
323 * take away our volume.
325 nvol->dev = NULL; /* don't zap dev entry */
328 /* Check if we are trying to use the Volume on a different drive */
329 if (dev != vol->dev) {
330 /* Caller wants to switch Volume to another device */
331 if (!vol->dev->is_busy()) {
332 /* OK to move it -- I'm not sure this will work */
333 Dmsg3(100, "==== Swap vol=%s from dev=%s to %s\n", VolumeName,
334 vol->dev->print_name(), dev->print_name());
335 vol->dev->vol = NULL; /* take vol from old drive */
336 vol->dev->VolHdr.VolumeName[0] = 0;
337 vol->dev = dev; /* point vol at new drive */
338 dev->vol = vol; /* point dev at vol */
339 dev->VolHdr.VolumeName[0] = 0;
341 Dmsg3(100, "Volume busy could not swap vol=%s from dev=%s to %s\n", VolumeName,
342 vol->dev->print_name(), dev->print_name());
343 vol = NULL; /* device busy */
350 debug_list_volumes("end new volume", debug_nolock);
356 * Search for a Volume name in the Volume list.
358 * Returns: VOLRES entry on success
359 * NULL if the Volume is not in the list
361 VOLRES *find_volume(const char *VolumeName)
364 /* Do not lock reservations here */
366 vol.vol_name = bstrdup(VolumeName);
367 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
369 Dmsg2(100, "find_vol=%s found=%d\n", VolumeName, fvol!=NULL);
370 debug_list_volumes("find_volume", debug_nolock);
376 * Remove any reservation from a drive and tell the system
377 * that the volume is unused at least by us.
379 void unreserve_device(DCR *dcr)
381 DEVICE *dev = dcr->dev;
383 if (dcr->reserved_device) {
384 dcr->reserved_device = false;
385 dev->reserved_device--;
386 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
387 dcr->reserved_device = false;
388 /* If we set read mode in reserving, remove it */
389 if (dev->can_read()) {
392 if (dev->num_writers < 0) {
393 Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
394 dev->num_writers = 0;
403 * Free a Volume from the Volume list if it is no longer used
405 * Returns: true if the Volume found and removed from the list
406 * false if the Volume is not in the list or is in use
408 bool volume_unused(DCR *dcr)
410 DEVICE *dev = dcr->dev;
412 if (dev->vol == NULL) {
413 Dmsg1(100, " unreserve_volume: no vol on %s\n", dev->print_name());
414 debug_list_volumes("null return unreserve_volume", debug_lock);
418 if (dev->is_busy()) {
419 Dmsg1(100, "unreserve_volume: dev is busy %s\n", dev->print_name());
420 debug_list_volumes("dev busy return unreserve_volume", debug_lock);
424 return free_volume(dev);
428 * Unconditionally release the volume
430 bool free_volume(DEVICE *dev)
434 if (dev->vol == NULL) {
435 Dmsg1(100, "No vol on dev %s\n", dev->print_name());
441 Dmsg1(100, "free_volume %s\n", vol->vol_name);
442 vol_list->remove(vol);
443 Dmsg3(100, "free_volume %s at %p dev=%s\n", vol->vol_name, vol->vol_name,
446 debug_list_volumes("free_volume", debug_nolock);
452 /* Create the Volume list */
453 void create_volume_list()
455 VOLRES *dummy = NULL;
456 if (vol_list == NULL) {
457 vol_list = New(dlist(dummy, &dummy->link));
461 /* Release all Volumes from the list */
462 void free_volume_list()
469 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
470 Dmsg2(100, "Unreleased Volume=%s dev=%p\n", vol->vol_name, vol->dev);
472 vol->vol_name = NULL;
479 bool is_volume_in_use(DCR *dcr)
481 VOLRES *vol = find_volume(dcr->VolumeName);
483 Dmsg1(100, "Vol=%s not in use.\n", dcr->VolumeName);
484 return false; /* vol not in list */
486 ASSERT(vol->dev != NULL);
488 if (dcr->dev == vol->dev) { /* same device OK */
489 Dmsg1(100, "Vol=%s on same dev.\n", dcr->VolumeName);
492 if (!vol->dev->is_busy()) {
493 Dmsg2(100, "Vol=%s dev=%s not busy.\n", dcr->VolumeName, vol->dev->print_name());
496 Dmsg2(100, "Vol=%s used by %s.\n", dcr->VolumeName, vol->dev->print_name());
502 * We get the following type of information:
504 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
508 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
512 static bool use_storage_cmd(JCR *jcr)
514 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
515 BSOCK *dir = jcr->dir_bsock;
525 memset(&rctx, 0, sizeof(RCTX));
528 * If there are multiple devices, the director sends us
529 * use_device for each device that it wants to use.
531 dirstore = New(alist(10, not_owned_by_alist));
532 // Dmsg2(000, "dirstore=%p JobId=%u\n", dirstore, jcr->JobId);
533 msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
535 Dmsg1(100, "<dird: %s", dir->msg);
536 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
537 media_type.c_str(), pool_name.c_str(),
538 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
543 jcr->write_store = dirstore;
545 jcr->read_store = dirstore;
547 rctx.append = append;
548 unbash_spaces(store_name);
549 unbash_spaces(media_type);
550 unbash_spaces(pool_name);
551 unbash_spaces(pool_type);
552 store = new DIRSTORE;
553 dirstore->append(store);
554 memset(store, 0, sizeof(DIRSTORE));
555 store->device = New(alist(10));
556 bstrncpy(store->name, store_name, sizeof(store->name));
557 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
558 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
559 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
560 store->append = append;
562 /* Now get all devices */
563 while (dir->recv() >= 0) {
564 Dmsg1(100, "<dird device: %s", dir->msg);
565 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
569 unbash_spaces(dev_name);
570 store->device->append(bstrdup(dev_name.c_str()));
572 } while (ok && dir->recv() >= 0);
575 /* This loop is debug code and can be removed */
576 /* ***FIXME**** remove after 1.38 release */
578 foreach_alist(store, dirstore) {
579 Dmsg6(110, "JobId=%u Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n",
580 (int)rctx.jcr->JobId,
581 store->name, store->media_type, store->pool_name,
582 store->pool_type, store->append);
583 foreach_alist(device_name, store->device) {
584 Dmsg1(110, " Device=%s\n", device_name);
589 init_jcr_device_wait_timers(jcr);
591 * At this point, we have a list of all the Director's Storage
592 * resources indicated for this Job, which include Pool, PoolType,
593 * storage name, and Media type.
594 * Then for each of the Storage resources, we have a list of
595 * device names that were given.
597 * Wiffle through them and find one that can do the backup.
600 int retries = 0; /* wait for device retries */
602 rctx.notify_dir = true;
604 for ( ; !fail && !job_canceled(jcr); ) {
605 while ((msg = (char *)msgs->pop())) {
608 rctx.suitable_device = false;
609 rctx.have_volume = false;
610 rctx.VolumeName[0] = 0;
611 rctx.any_drive = false;
612 if (!jcr->PreferMountedVols) {
613 /* Look for unused drives in autochangers */
614 rctx.num_writers = 20000000; /* start with impossible number */
615 rctx.low_use_drive = NULL;
616 rctx.PreferMountedVols = false;
617 rctx.exact_match = false;
618 rctx.autochanger_only = true;
619 Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
620 (int)rctx.jcr->JobId,
621 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
622 rctx.autochanger_only, rctx.any_drive);
623 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
626 /* Look through all drives possibly for low_use drive */
627 if (rctx.low_use_drive) {
628 rctx.try_low_use_drive = true;
629 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
632 rctx.try_low_use_drive = false;
634 rctx.autochanger_only = false;
635 Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
636 (int)rctx.jcr->JobId,
637 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
638 rctx.autochanger_only, rctx.any_drive);
639 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
643 /* Look for an exact match all drives */
644 rctx.PreferMountedVols = true;
645 rctx.exact_match = true;
646 rctx.autochanger_only = false;
647 Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
648 (int)rctx.jcr->JobId,
649 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
650 rctx.autochanger_only, rctx.any_drive);
651 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
654 /* Look for any mounted drive */
655 rctx.exact_match = false;
656 Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
657 (int)rctx.jcr->JobId,
658 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
659 rctx.autochanger_only, rctx.any_drive);
660 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
664 rctx.any_drive = true;
665 Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
666 (int)rctx.jcr->JobId,
667 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
668 rctx.autochanger_only, rctx.any_drive);
669 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
672 /* Keep reservations locked *except* during wait_for_device() */
673 unlock_reservations();
674 if (!rctx.suitable_device || !wait_for_device(jcr, retries)) {
675 Dmsg1(100, "JobId=%u Fail. !suitable_device || !wait_for_device\n",
676 (int)rctx.jcr->JobId);
680 bnet_sig(dir, BNET_HEARTBEAT); /* Inform Dir that we are alive */
682 unlock_reservations();
685 * If we get here, there are no suitable devices available, which
686 * means nothing configured. If a device is suitable but busy
687 * with another Volume, we will not come here.
689 unbash_spaces(dir->msg);
690 pm_strcpy(jcr->errmsg, dir->msg);
691 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
692 Jmsg(jcr, M_FATAL, 0, _("\n"
693 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
694 dev_name.c_str(), media_type.c_str());
695 bnet_fsend(dir, NO_device, dev_name.c_str());
697 Dmsg1(100, ">dird: %s", dir->msg);
700 unbash_spaces(dir->msg);
701 pm_strcpy(jcr->errmsg, dir->msg);
702 Jmsg(jcr, M_FATAL, 0, _("Failed command: %s\n"), jcr->errmsg);
703 bnet_fsend(dir, BAD_use, jcr->errmsg);
704 Dmsg1(100, ">dird: %s", dir->msg);
711 void release_msgs(JCR *jcr)
713 alist *msgs = jcr->reserve_msgs;
720 while ((msg = (char *)msgs->pop())) {
724 jcr->reserve_msgs = NULL;
725 unlock_reservations();
729 * Search for a device suitable for this job.
731 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
739 dirstore = jcr->write_store;
741 dirstore = jcr->read_store;
744 * For each storage device that the user specified, we
745 * search and see if there is a resource for that device.
747 Dmsg5(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
748 (int)rctx.jcr->JobId,
749 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
750 rctx.autochanger_only);
752 foreach_alist(store, dirstore) {
754 foreach_alist(device_name, store->device) {
756 rctx.device_name = device_name;
757 stat = search_res_for_device(rctx);
758 if (stat == 1) { /* found available device */
759 Dmsg2(100, "JobId=%u Suitable device found=%s\n", (int)rctx.jcr->JobId,
763 } else if (stat == 0) { /* device busy */
764 Dmsg2(110, "JobId=%u Suitable device=%s, busy: not use\n",
765 (int)rctx.jcr->JobId, device_name);
767 /* otherwise error */
768 Dmsg1(110, "JobId=%u No suitable device found.\n", (int)rctx.jcr->JobId);
779 * Search for a particular storage device with particular storage
780 * characteristics (MediaType).
782 int search_res_for_device(RCTX &rctx)
784 AUTOCHANGER *changer;
785 BSOCK *dir = rctx.jcr->dir_bsock;
789 Dmsg2(110, "JobId=%u search res for %s\n", (int)rctx.jcr->JobId, rctx.device_name);
790 /* Look through Autochangers first */
791 foreach_res(changer, R_AUTOCHANGER) {
792 Dmsg2(150, "JobId=%u Try match changer res=%s\n", (int)rctx.jcr->JobId, changer->hdr.name);
793 /* Find resource, and make sure we were able to open it */
794 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
795 /* Try each device in this AutoChanger */
796 foreach_alist(rctx.device, changer->device) {
797 Dmsg2(110, "JobId=%u Try changer device %s\n", (int)rctx.jcr->JobId,
798 rctx.device->hdr.name);
799 stat = reserve_device(rctx);
800 if (stat != 1) { /* try another device */
804 if (rctx.store->append == SD_APPEND) {
805 Dmsg3(100, "JobId=%u Device %s reserved=%d for append.\n",
806 (int)rctx.jcr->JobId, rctx.device->hdr.name,
807 rctx.jcr->dcr->dev->reserved_device);
809 Dmsg3(100, "JobId=%u Device %s reserved=%d for read.\n",
810 (int)rctx.jcr->JobId, rctx.device->hdr.name,
811 rctx.jcr->read_dcr->dev->reserved_device);
813 if (rctx.notify_dir) {
814 pm_strcpy(dev_name, rctx.device->hdr.name);
815 bash_spaces(dev_name);
816 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
817 Dmsg1(100, ">dird changer: %s", dir->msg);
826 /* Now if requested look through regular devices */
827 if (!rctx.autochanger_only) {
828 foreach_res(rctx.device, R_DEVICE) {
829 Dmsg2(150, "JobId=%u Try match res=%s\n", (int)rctx.jcr->JobId, rctx.device->hdr.name);
830 /* Find resource, and make sure we were able to open it */
831 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
832 stat = reserve_device(rctx);
836 if (rctx.notify_dir) {
837 bash_spaces(rctx.device_name);
838 ok = bnet_fsend(dir, OK_device, rctx.device_name);
839 Dmsg1(100, ">dird dev: %s", dir->msg);
847 return -1; /* nothing found */
851 * Try to reserve a specific device.
853 * Returns: 1 -- OK, have DCR
857 static int reserve_device(RCTX &rctx)
861 const int name_len = MAX_NAME_LENGTH;
863 /* Make sure MediaType is OK */
864 Dmsg3(110, "JobId=%u MediaType device=%s request=%s\n",
865 (int)rctx.jcr->JobId,
866 rctx.device->media_type, rctx.store->media_type);
867 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
871 /* Make sure device exists -- i.e. we can stat() it */
872 if (!rctx.device->dev) {
873 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
875 if (!rctx.device->dev) {
876 if (rctx.device->changer_res) {
877 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
878 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
879 rctx.device->hdr.name, rctx.device_name);
881 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
882 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
885 return -1; /* no use waiting */
888 rctx.suitable_device = true;
889 Dmsg2(110, "Try reserve %s JobId=%u\n", rctx.device->hdr.name,
891 dcr = new_dcr(rctx.jcr, rctx.device->dev);
893 BSOCK *dir = rctx.jcr->dir_bsock;
894 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
895 Dmsg1(100, ">dird: %s", dir->msg);
898 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
899 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
900 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
901 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
902 if (rctx.store->append == SD_APPEND) {
903 Dmsg3(100, "JobId=%u have_vol=%d vol=%s\n", (int)rctx.jcr->JobId,
904 rctx.have_volume, rctx.VolumeName);
905 if (!rctx.have_volume) {
906 dcr->any_volume = true;
907 if (dir_find_next_appendable_volume(dcr)) {
908 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
909 Dmsg2(100, "JobId=%u looking for Volume=%s\n", (int)rctx.jcr->JobId, rctx.VolumeName);
910 rctx.have_volume = true;
912 Dmsg1(100, "JobId=%u No next volume found\n", (int)rctx.jcr->JobId);
913 rctx.have_volume = false;
914 rctx.VolumeName[0] = 0;
917 ok = reserve_device_for_append(dcr, rctx);
920 Dmsg6(100, "JobId=%u Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
921 (int)rctx.jcr->JobId,
922 dcr->dev->reserved_device,
923 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
926 ok = reserve_device_for_read(dcr);
928 rctx.jcr->read_dcr = dcr;
929 Dmsg6(100, "JobId=%u Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
930 (int)rctx.jcr->JobId,
931 dcr->dev->reserved_device,
932 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
936 rctx.have_volume = false;
938 Dmsg1(110, "JobId=%u Not OK.\n", (int)rctx.jcr->JobId);
945 * We "reserve" the drive by setting the ST_READ bit. No one else
946 * should touch the drive until that is cleared.
947 * This allows the DIR to "reserve" the device before actually
950 static bool reserve_device_for_read(DCR *dcr)
952 DEVICE *dev = dcr->dev;
960 if (is_device_unmounted(dev)) {
961 Dmsg2(200, "JobId=%u Device %s is BLOCKED due to user unmount.\n",
962 (int)jcr->JobId, dev->print_name());
963 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
964 jcr->JobId, dev->print_name());
965 queue_reserve_message(jcr);
969 if (dev->is_busy()) {
970 Dmsg5(200, "JobId=%u Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n",
971 (int)jcr->JobId, dev->print_name(),
972 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
973 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
974 jcr->JobId, dev->print_name());
975 queue_reserve_message(jcr);
982 dev->reserved_device++;
983 Dmsg4(100, "JobId=%u Inc reserve=%d dev=%s %p\n", (int)jcr->JobId,
984 dev->reserved_device, dev->print_name(), dev);
985 dcr->reserved_device = true;
994 * We reserve the device for appending by incrementing the
995 * reserved_device. We do virtually all the same work that
996 * is done in acquire_device_for_append(), but we do
997 * not attempt to mount the device. This routine allows
998 * the DIR to reserve multiple devices before *really*
999 * starting the job. It also permits the SD to refuse
1000 * certain devices (not up, ...).
1002 * Note, in reserving a device, if the device is for the
1003 * same pool and the same pool type, then it is acceptable.
1004 * The Media Type has already been checked. If we are
1005 * the first tor reserve the device, we put the pool
1006 * name and pool type in the device record.
1008 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
1010 JCR *jcr = dcr->jcr;
1011 DEVICE *dev = dcr->dev;
1018 /* If device is being read, we cannot write it */
1019 if (dev->can_read()) {
1020 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
1021 jcr->JobId, dev->print_name());
1022 Dmsg1(110, "%s", jcr->errmsg);
1023 queue_reserve_message(jcr);
1027 /* If device is unmounted, we are out of luck */
1028 if (is_device_unmounted(dev)) {
1029 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
1030 jcr->JobId, dev->print_name());
1031 Dmsg1(110, "%s", jcr->errmsg);
1032 queue_reserve_message(jcr);
1036 Dmsg2(110, "JobId=%u reserve_append device is %s\n",
1037 (int)jcr->JobId, dev->is_tape()?"tape":"disk");
1039 /* Now do detailed tests ... */
1040 if (can_reserve_drive(dcr, rctx) != 1) {
1041 Dmsg1(110, "JobId=%u can_reserve_drive!=1\n", (int)jcr->JobId);
1045 dev->reserved_device++;
1046 Dmsg4(100, "JobId=%u Inc reserve=%d dev=%s %p\n", (int)jcr->JobId, dev->reserved_device,
1047 dev->print_name(), dev);
1048 dcr->reserved_device = true;
1057 * Returns: 1 if drive can be reserved
1058 * 0 if we should wait
1059 * -1 on error or impossibility
1061 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
1063 DEVICE *dev = dcr->dev;
1064 JCR *jcr = dcr->jcr;
1066 Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
1068 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1069 rctx.autochanger_only, rctx.any_drive);
1071 /* setting any_drive overrides PreferMountedVols flag */
1072 if (!rctx.any_drive) {
1074 * When PreferMountedVols is set, we keep track of the
1075 * drive in use that has the least number of writers, then if
1076 * no unmounted drive is found, we try that drive. This
1077 * helps spread the load to the least used drives.
1079 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
1080 Dmsg3(110, "OK dev=%s == low_drive=%s. JobId=%u\n",
1081 dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
1084 /* If he wants a free drive, but this one is busy, no go */
1085 if (!rctx.PreferMountedVols && dev->is_busy()) {
1086 /* Save least used drive */
1087 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
1088 rctx.num_writers = dev->num_writers + dev->reserved_device;
1089 rctx.low_use_drive = dev;
1090 Dmsg3(110, "JobId=%u set low use drive=%s num_writers=%d\n",
1091 (int)jcr->JobId, dev->print_name(), rctx.num_writers);
1093 Dmsg2(110, "JobId=%u not low use num_writers=%d\n",
1094 (int)jcr->JobId, dev->num_writers+dev->reserved_device);
1096 Dmsg1(110, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
1097 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
1098 jcr->JobId, dev->print_name());
1099 queue_reserve_message(jcr);
1103 /* Check for prefer mounted volumes */
1104 // if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
1105 if (rctx.PreferMountedVols && !dev->vol && dev->is_tape()) {
1106 Mmsg(jcr->errmsg, _("3606 JobId=%u prefers mounted drives, but drive %s has no Volume.\n"),
1107 jcr->JobId, dev->print_name());
1108 queue_reserve_message(jcr);
1109 Dmsg1(110, "failed: want mounted -- no vol JobId=%u\n", (uint32_t)jcr->JobId);
1110 return 0; /* No volume mounted */
1113 /* Check for exact Volume name match */
1114 /* ***FIXME*** use dev->vol.VolumeName */
1115 if (rctx.exact_match && rctx.have_volume &&
1116 strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
1117 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
1118 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
1120 queue_reserve_message(jcr);
1121 Dmsg3(110, "JobId=%u failed: Not exact match have=%s want=%s\n",
1122 (int)jcr->JobId, dev->VolHdr.VolumeName, rctx.VolumeName);
1127 /* Check for unused autochanger drive */
1128 /* ***FIXME*** use !dev->is_busy() */
1129 if (rctx.autochanger_only && dev->num_writers == 0 &&
1130 dev->VolHdr.VolumeName[0] == 0) {
1131 /* Device is available but not yet reserved, reserve it for us */
1132 Dmsg2(100, "OK Res Unused autochanger %s JobId=%u.\n",
1133 dev->print_name(), jcr->JobId);
1134 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1135 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1136 return 1; /* reserve drive */
1140 * Handle the case that there are no writers
1142 if (dev->num_writers == 0) {
1143 /* Now check if there are any reservations on the drive */
1144 if (dev->reserved_device) {
1145 /* Now check if we want the same Pool and pool type */
1146 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1147 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1148 /* OK, compatible device */
1149 Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
1150 dev->print_name(), jcr->JobId);
1153 /* Drive Pool not suitable for us */
1154 Mmsg(jcr->errmsg, _(
1155 "3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"),
1156 jcr->JobId, dcr->pool_name, dev->pool_name,
1157 dev->reserved_device, dev->print_name());
1158 queue_reserve_message(jcr);
1159 Dmsg3(110, "JobId=%u failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
1160 (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1161 return 0; /* wait */
1163 } else if (dev->can_append()) {
1164 /* Device in append mode, check if changing pool */
1165 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1166 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1167 Dmsg2(100, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
1168 dev->print_name(), jcr->JobId);
1169 /* OK, compatible device */
1172 /* Changing pool, unload old tape if any in drive */
1173 Dmsg1(100, "JobId=%u OK dev: num_writers=0, not reserved, pool change, unload changer\n",
1175 unload_autochanger(dcr, 0);
1178 /* Device is available but not yet reserved, reserve it for us */
1179 Dmsg2(100, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
1181 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1182 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1183 return 1; /* reserve drive */
1187 * Check if the device is in append mode with writers (i.e.
1188 * available if pool is the same).
1190 if (dev->can_append() || dev->num_writers > 0) {
1191 /* Yes, now check if we want the same Pool and pool type */
1192 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1193 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1194 Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
1195 dev->print_name(), jcr->JobId);
1196 /* OK, compatible device */
1199 /* Drive Pool not suitable for us */
1200 Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but has Pool=\"%s\" on drive %s.\n"),
1201 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
1202 queue_reserve_message(jcr);
1203 Dmsg3(110, "JobId=%u failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
1204 (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1205 return 0; /* wait */
1208 Pmsg1(000, _("Logic error!!!! JobId=%u Should not get here.\n"), (int)jcr->JobId);
1209 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
1210 jcr->JobId, dev->print_name());
1211 queue_reserve_message(jcr);
1212 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
1213 return -1; /* error, should not get here */
1215 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
1216 jcr->JobId, dev->print_name());
1217 queue_reserve_message(jcr);
1218 Dmsg2(110, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
1223 * search_lock is already set on entering this routine
1225 static void queue_reserve_message(JCR *jcr)
1228 alist *msgs = jcr->reserve_msgs;
1235 * Look for duplicate message. If found, do
1238 for (i=msgs->size()-1; i >= 0; i--) {
1239 msg = (char *)msgs->get(i);
1243 /* Comparison based on 4 digit message number */
1244 if (strncmp(msg, jcr->errmsg, 4) == 0) {
1248 /* Message unique, so insert it */
1249 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1253 * Send any reservation messages queued for this jcr
1255 void send_drive_reserve_messages(JCR *jcr, void sendit(const char *msg, int len, void *sarg), void *arg)
1261 lock_reservations();
1262 msgs = jcr->reserve_msgs;
1263 if (!msgs || msgs->size() == 0) {
1264 unlock_reservations();
1267 for (i=msgs->size()-1; i >= 0; i--) {
1268 msg = (char *)msgs->get(i);
1270 sendit(" ", 3, arg);
1271 sendit(msg, strlen(msg), arg);
1276 unlock_reservations();