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.
263 * Return: VOLRES entry on success
264 * NULL volume busy on another drive
266 VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
269 DEVICE *dev = dcr->dev;
273 Dmsg1(100, "reserve_volume %s\n", VolumeName);
275 * We lock the reservations system here to ensure
276 * when adding a new volume that no newly scheduled
277 * job can reserve it.
280 debug_list_volumes("begin reserve_volume", debug_nolock);
282 * First, remove any old volume attached to this device as it
288 * Make sure we don't remove the current volume we are inserting
289 * because it was probably inserted by another job.
291 if (strcmp(vol->vol_name, VolumeName) == 0) {
292 goto get_out; /* Volume already on this device */
294 Dmsg3(100, "reserve_vol free vol=%s at %p JobId=%u\n", vol->vol_name,
295 vol->vol_name, (int)dcr->jcr->JobId);
296 debug_list_volumes("reserve_vol free", debug_nolock);
297 vol_list->remove(vol);
302 /* Create a new Volume entry */
303 nvol = new_vol_item(dcr, VolumeName);
306 * Now try to insert the new Volume
308 vol = (VOLRES *)vol_list->binary_insert(nvol, my_compare);
310 Dmsg2(100, "Found vol=%s dev-same=%d\n", vol->vol_name, dev==vol->dev);
312 * At this point, a Volume with this name already is in the list,
313 * so we simply release our new Volume entry. Note, this should
314 * only happen if we are moving the volume from one drive to another.
316 Dmsg3(100, "reserve_vol free-tmp vol=%s at %p JobId=%u\n", vol->vol_name,
317 vol->vol_name, (int)dcr->jcr->JobId);
319 * Clear dev pointer so that free_vol_item() doesn't
320 * take away our volume.
322 nvol->dev = NULL; /* don't zap dev entry */
325 /* Check if we are trying to use the Volume on a different drive */
326 if (dev != vol->dev) {
327 /* Caller wants to switch Volume to another device */
328 if (!vol->dev->is_busy()) {
329 /* OK to move it -- I'm not sure this will work */
330 Dmsg3(100, "==== Swap vol=%s from dev=%s to %s\n", VolumeName,
331 vol->dev->print_name(), dev->print_name());
332 vol->dev->vol = NULL; /* take vol from old drive */
333 vol->dev->VolHdr.VolumeName[0] = 0;
334 vol->dev = dev; /* point vol at new drive */
335 dev->vol = vol; /* point dev at vol */
336 dev->VolHdr.VolumeName[0] = 0;
338 Dmsg3(100, "Volume busy could not swap vol=%s from dev=%s to %s\n", VolumeName,
339 vol->dev->print_name(), dev->print_name());
340 vol = NULL; /* device busy */
347 debug_list_volumes("end new volume", debug_nolock);
353 * Search for a Volume name in the Volume list.
355 * Returns: VOLRES entry on success
356 * NULL if the Volume is not in the list
358 VOLRES *find_volume(const char *VolumeName)
361 /* Do not lock reservations here */
363 vol.vol_name = bstrdup(VolumeName);
364 fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
366 Dmsg2(100, "find_vol=%s found=%d\n", VolumeName, fvol!=NULL);
367 debug_list_volumes("find_volume", debug_nolock);
373 * Remove any reservation from a drive and tell the system
374 * that the volume is unused at least by us.
376 void unreserve_device(DCR *dcr)
378 DEVICE *dev = dcr->dev;
380 if (dcr->reserved_device) {
381 dcr->reserved_device = false;
382 dev->reserved_device--;
383 Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
384 dcr->reserved_device = false;
385 /* If we set read mode in reserving, remove it */
386 if (dev->can_read()) {
389 if (dev->num_writers < 0) {
390 Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
391 dev->num_writers = 0;
400 * Free a Volume from the Volume list if it is no longer used
402 * Returns: true if the Volume found and removed from the list
403 * false if the Volume is not in the list or is in use
405 bool volume_unused(DCR *dcr)
407 DEVICE *dev = dcr->dev;
409 if (dev->vol == NULL) {
410 Dmsg1(100, " unreserve_volume: no vol on %s\n", dev->print_name());
411 debug_list_volumes("null return unreserve_volume", debug_lock);
415 if (dev->is_busy()) {
416 Dmsg1(100, "unreserve_volume: dev is busy %s\n", dev->print_name());
417 debug_list_volumes("dev busy return unreserve_volume", debug_lock);
421 return free_volume(dev);
425 * Unconditionally release the volume
427 bool free_volume(DEVICE *dev)
431 if (dev->vol == NULL) {
432 Dmsg1(100, "No vol on dev %s\n", dev->print_name());
438 Dmsg1(100, "free_volume %s\n", vol->vol_name);
439 vol_list->remove(vol);
440 Dmsg3(100, "free_volume %s at %p dev=%s\n", vol->vol_name, vol->vol_name,
443 debug_list_volumes("free_volume", debug_nolock);
449 /* Create the Volume list */
450 void create_volume_list()
452 VOLRES *dummy = NULL;
453 if (vol_list == NULL) {
454 vol_list = New(dlist(dummy, &dummy->link));
458 /* Release all Volumes from the list */
459 void free_volume_list()
466 for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
467 Dmsg2(100, "Unreleased Volume=%s dev=%p\n", vol->vol_name, vol->dev);
469 vol->vol_name = NULL;
476 bool is_volume_in_use(DCR *dcr)
478 VOLRES *vol = find_volume(dcr->VolumeName);
480 Dmsg1(100, "Vol=%s not in use.\n", dcr->VolumeName);
481 return false; /* vol not in list */
483 ASSERT(vol->dev != NULL);
485 if (dcr->dev == vol->dev) { /* same device OK */
486 Dmsg1(100, "Vol=%s on same dev.\n", dcr->VolumeName);
489 if (!vol->dev->is_busy()) {
490 Dmsg2(100, "Vol=%s dev=%s not busy.\n", dcr->VolumeName, vol->dev->print_name());
493 Dmsg2(100, "Vol=%s used by %s.\n", dcr->VolumeName, vol->dev->print_name());
499 * We get the following type of information:
501 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
505 * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
509 static bool use_storage_cmd(JCR *jcr)
511 POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
512 BSOCK *dir = jcr->dir_bsock;
522 memset(&rctx, 0, sizeof(RCTX));
525 * If there are multiple devices, the director sends us
526 * use_device for each device that it wants to use.
528 dirstore = New(alist(10, not_owned_by_alist));
529 // Dmsg2(000, "dirstore=%p JobId=%u\n", dirstore, jcr->JobId);
530 msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
532 Dmsg1(100, "<dird: %s", dir->msg);
533 ok = sscanf(dir->msg, use_storage, store_name.c_str(),
534 media_type.c_str(), pool_name.c_str(),
535 pool_type.c_str(), &append, &Copy, &Stripe) == 7;
540 jcr->write_store = dirstore;
542 jcr->read_store = dirstore;
544 rctx.append = append;
545 unbash_spaces(store_name);
546 unbash_spaces(media_type);
547 unbash_spaces(pool_name);
548 unbash_spaces(pool_type);
549 store = new DIRSTORE;
550 dirstore->append(store);
551 memset(store, 0, sizeof(DIRSTORE));
552 store->device = New(alist(10));
553 bstrncpy(store->name, store_name, sizeof(store->name));
554 bstrncpy(store->media_type, media_type, sizeof(store->media_type));
555 bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
556 bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
557 store->append = append;
559 /* Now get all devices */
560 while (dir->recv() >= 0) {
561 Dmsg1(100, "<dird device: %s", dir->msg);
562 ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
566 unbash_spaces(dev_name);
567 store->device->append(bstrdup(dev_name.c_str()));
569 } while (ok && dir->recv() >= 0);
572 /* This loop is debug code and can be removed */
573 /* ***FIXME**** remove after 1.38 release */
575 foreach_alist(store, dirstore) {
576 Dmsg6(110, "JobId=%u Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n",
577 (int)rctx.jcr->JobId,
578 store->name, store->media_type, store->pool_name,
579 store->pool_type, store->append);
580 foreach_alist(device_name, store->device) {
581 Dmsg1(110, " Device=%s\n", device_name);
586 init_jcr_device_wait_timers(jcr);
588 * At this point, we have a list of all the Director's Storage
589 * resources indicated for this Job, which include Pool, PoolType,
590 * storage name, and Media type.
591 * Then for each of the Storage resources, we have a list of
592 * device names that were given.
594 * Wiffle through them and find one that can do the backup.
597 int retries = 0; /* wait for device retries */
599 rctx.notify_dir = true;
601 for ( ; !fail && !job_canceled(jcr); ) {
602 while ((msg = (char *)msgs->pop())) {
605 rctx.suitable_device = false;
606 rctx.have_volume = false;
607 rctx.VolumeName[0] = 0;
608 rctx.any_drive = false;
609 if (!jcr->PreferMountedVols) {
610 /* Look for unused drives in autochangers */
611 rctx.num_writers = 20000000; /* start with impossible number */
612 rctx.low_use_drive = NULL;
613 rctx.PreferMountedVols = false;
614 rctx.exact_match = false;
615 rctx.autochanger_only = true;
616 Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
617 (int)rctx.jcr->JobId,
618 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
619 rctx.autochanger_only, rctx.any_drive);
620 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
623 /* Look through all drives possibly for low_use drive */
624 if (rctx.low_use_drive) {
625 rctx.try_low_use_drive = true;
626 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
629 rctx.try_low_use_drive = false;
631 rctx.autochanger_only = false;
632 Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
633 (int)rctx.jcr->JobId,
634 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
635 rctx.autochanger_only, rctx.any_drive);
636 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
640 /* Look for an exact match all drives */
641 rctx.PreferMountedVols = true;
642 rctx.exact_match = true;
643 rctx.autochanger_only = false;
644 Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
645 (int)rctx.jcr->JobId,
646 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
647 rctx.autochanger_only, rctx.any_drive);
648 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
651 /* Look for any mounted drive */
652 rctx.exact_match = false;
653 Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
654 (int)rctx.jcr->JobId,
655 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
656 rctx.autochanger_only, rctx.any_drive);
657 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
661 rctx.any_drive = true;
662 Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
663 (int)rctx.jcr->JobId,
664 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
665 rctx.autochanger_only, rctx.any_drive);
666 if ((ok = find_suitable_device_for_job(jcr, rctx))) {
669 /* Keep reservations locked *except* during wait_for_device() */
670 unlock_reservations();
671 if (!rctx.suitable_device || !wait_for_device(jcr, retries)) {
672 Dmsg1(100, "JobId=%u Fail. !suitable_device || !wait_for_device\n",
673 (int)rctx.jcr->JobId);
677 bnet_sig(dir, BNET_HEARTBEAT); /* Inform Dir that we are alive */
679 unlock_reservations();
682 * If we get here, there are no suitable devices available, which
683 * means nothing configured. If a device is suitable but busy
684 * with another Volume, we will not come here.
686 unbash_spaces(dir->msg);
687 pm_strcpy(jcr->errmsg, dir->msg);
688 Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
689 Jmsg(jcr, M_FATAL, 0, _("\n"
690 " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
691 dev_name.c_str(), media_type.c_str());
692 bnet_fsend(dir, NO_device, dev_name.c_str());
694 Dmsg1(100, ">dird: %s", dir->msg);
697 unbash_spaces(dir->msg);
698 pm_strcpy(jcr->errmsg, dir->msg);
699 Jmsg(jcr, M_FATAL, 0, _("Failed command: %s\n"), jcr->errmsg);
700 bnet_fsend(dir, BAD_use, jcr->errmsg);
701 Dmsg1(100, ">dird: %s", dir->msg);
708 void release_msgs(JCR *jcr)
710 alist *msgs = jcr->reserve_msgs;
717 while ((msg = (char *)msgs->pop())) {
721 jcr->reserve_msgs = NULL;
722 unlock_reservations();
726 * Search for a device suitable for this job.
728 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
736 dirstore = jcr->write_store;
738 dirstore = jcr->read_store;
741 * For each storage device that the user specified, we
742 * search and see if there is a resource for that device.
744 Dmsg5(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
745 (int)rctx.jcr->JobId,
746 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
747 rctx.autochanger_only);
749 foreach_alist(store, dirstore) {
751 foreach_alist(device_name, store->device) {
753 rctx.device_name = device_name;
754 stat = search_res_for_device(rctx);
755 if (stat == 1) { /* found available device */
756 Dmsg2(100, "JobId=%u Suitable device found=%s\n", (int)rctx.jcr->JobId,
760 } else if (stat == 0) { /* device busy */
761 Dmsg2(110, "JobId=%u Suitable device=%s, busy: not use\n",
762 (int)rctx.jcr->JobId, device_name);
764 /* otherwise error */
765 Dmsg1(110, "JobId=%u No suitable device found.\n", (int)rctx.jcr->JobId);
776 * Search for a particular storage device with particular storage
777 * characteristics (MediaType).
779 int search_res_for_device(RCTX &rctx)
781 AUTOCHANGER *changer;
782 BSOCK *dir = rctx.jcr->dir_bsock;
786 Dmsg2(110, "JobId=%u search res for %s\n", (int)rctx.jcr->JobId, rctx.device_name);
787 /* Look through Autochangers first */
788 foreach_res(changer, R_AUTOCHANGER) {
789 Dmsg2(150, "JobId=%u Try match changer res=%s\n", (int)rctx.jcr->JobId, changer->hdr.name);
790 /* Find resource, and make sure we were able to open it */
791 if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
792 /* Try each device in this AutoChanger */
793 foreach_alist(rctx.device, changer->device) {
794 Dmsg2(110, "JobId=%u Try changer device %s\n", (int)rctx.jcr->JobId,
795 rctx.device->hdr.name);
796 stat = reserve_device(rctx);
797 if (stat != 1) { /* try another device */
801 if (rctx.store->append == SD_APPEND) {
802 Dmsg3(100, "JobId=%u Device %s reserved=%d for append.\n",
803 (int)rctx.jcr->JobId, rctx.device->hdr.name,
804 rctx.jcr->dcr->dev->reserved_device);
806 Dmsg3(100, "JobId=%u Device %s reserved=%d for read.\n",
807 (int)rctx.jcr->JobId, rctx.device->hdr.name,
808 rctx.jcr->read_dcr->dev->reserved_device);
810 if (rctx.notify_dir) {
811 pm_strcpy(dev_name, rctx.device->hdr.name);
812 bash_spaces(dev_name);
813 ok = bnet_fsend(dir, OK_device, dev_name.c_str()); /* Return real device name */
814 Dmsg1(100, ">dird changer: %s", dir->msg);
823 /* Now if requested look through regular devices */
824 if (!rctx.autochanger_only) {
825 foreach_res(rctx.device, R_DEVICE) {
826 Dmsg2(150, "JobId=%u Try match res=%s\n", (int)rctx.jcr->JobId, rctx.device->hdr.name);
827 /* Find resource, and make sure we were able to open it */
828 if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
829 stat = reserve_device(rctx);
833 if (rctx.notify_dir) {
834 bash_spaces(rctx.device_name);
835 ok = bnet_fsend(dir, OK_device, rctx.device_name);
836 Dmsg1(100, ">dird dev: %s", dir->msg);
844 return -1; /* nothing found */
848 * Try to reserve a specific device.
850 * Returns: 1 -- OK, have DCR
854 static int reserve_device(RCTX &rctx)
858 const int name_len = MAX_NAME_LENGTH;
860 /* Make sure MediaType is OK */
861 Dmsg3(110, "JobId=%u MediaType device=%s request=%s\n",
862 (int)rctx.jcr->JobId,
863 rctx.device->media_type, rctx.store->media_type);
864 if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
868 /* Make sure device exists -- i.e. we can stat() it */
869 if (!rctx.device->dev) {
870 rctx.device->dev = init_dev(rctx.jcr, rctx.device);
872 if (!rctx.device->dev) {
873 if (rctx.device->changer_res) {
874 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
875 " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
876 rctx.device->hdr.name, rctx.device_name);
878 Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
879 " Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
882 return -1; /* no use waiting */
885 rctx.suitable_device = true;
886 Dmsg2(110, "Try reserve %s JobId=%u\n", rctx.device->hdr.name,
888 dcr = new_dcr(rctx.jcr, rctx.device->dev);
890 BSOCK *dir = rctx.jcr->dir_bsock;
891 bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
892 Dmsg1(100, ">dird: %s", dir->msg);
895 bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
896 bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
897 bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
898 bstrncpy(dcr->dev_name, rctx.device_name, name_len);
899 if (rctx.store->append == SD_APPEND) {
900 Dmsg3(100, "JobId=%u have_vol=%d vol=%s\n", (int)rctx.jcr->JobId,
901 rctx.have_volume, rctx.VolumeName);
902 if (!rctx.have_volume) {
903 dcr->any_volume = true;
904 if (dir_find_next_appendable_volume(dcr)) {
905 bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
906 Dmsg2(100, "JobId=%u looking for Volume=%s\n", (int)rctx.jcr->JobId, rctx.VolumeName);
907 rctx.have_volume = true;
909 Dmsg1(100, "JobId=%u No next volume found\n", (int)rctx.jcr->JobId);
910 rctx.have_volume = false;
911 rctx.VolumeName[0] = 0;
914 ok = reserve_device_for_append(dcr, rctx);
917 Dmsg6(100, "JobId=%u Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
918 (int)rctx.jcr->JobId,
919 dcr->dev->reserved_device,
920 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
923 ok = reserve_device_for_read(dcr);
925 rctx.jcr->read_dcr = dcr;
926 Dmsg6(100, "JobId=%u Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
927 (int)rctx.jcr->JobId,
928 dcr->dev->reserved_device,
929 dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
933 rctx.have_volume = false;
935 Dmsg1(110, "JobId=%u Not OK.\n", (int)rctx.jcr->JobId);
942 * We "reserve" the drive by setting the ST_READ bit. No one else
943 * should touch the drive until that is cleared.
944 * This allows the DIR to "reserve" the device before actually
947 static bool reserve_device_for_read(DCR *dcr)
949 DEVICE *dev = dcr->dev;
957 if (is_device_unmounted(dev)) {
958 Dmsg2(200, "JobId=%u Device %s is BLOCKED due to user unmount.\n",
959 (int)jcr->JobId, dev->print_name());
960 Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
961 jcr->JobId, dev->print_name());
962 queue_reserve_message(jcr);
966 if (dev->is_busy()) {
967 Dmsg5(200, "JobId=%u Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n",
968 (int)jcr->JobId, dev->print_name(),
969 dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
970 Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
971 jcr->JobId, dev->print_name());
972 queue_reserve_message(jcr);
979 dev->reserved_device++;
980 Dmsg4(100, "JobId=%u Inc reserve=%d dev=%s %p\n", (int)jcr->JobId,
981 dev->reserved_device, dev->print_name(), dev);
982 dcr->reserved_device = true;
991 * We reserve the device for appending by incrementing the
992 * reserved_device. We do virtually all the same work that
993 * is done in acquire_device_for_append(), but we do
994 * not attempt to mount the device. This routine allows
995 * the DIR to reserve multiple devices before *really*
996 * starting the job. It also permits the SD to refuse
997 * certain devices (not up, ...).
999 * Note, in reserving a device, if the device is for the
1000 * same pool and the same pool type, then it is acceptable.
1001 * The Media Type has already been checked. If we are
1002 * the first tor reserve the device, we put the pool
1003 * name and pool type in the device record.
1005 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
1007 JCR *jcr = dcr->jcr;
1008 DEVICE *dev = dcr->dev;
1015 /* If device is being read, we cannot write it */
1016 if (dev->can_read()) {
1017 Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"),
1018 jcr->JobId, dev->print_name());
1019 Dmsg1(110, "%s", jcr->errmsg);
1020 queue_reserve_message(jcr);
1024 /* If device is unmounted, we are out of luck */
1025 if (is_device_unmounted(dev)) {
1026 Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"),
1027 jcr->JobId, dev->print_name());
1028 Dmsg1(110, "%s", jcr->errmsg);
1029 queue_reserve_message(jcr);
1033 Dmsg2(110, "JobId=%u reserve_append device is %s\n",
1034 (int)jcr->JobId, dev->is_tape()?"tape":"disk");
1036 /* Now do detailed tests ... */
1037 if (can_reserve_drive(dcr, rctx) != 1) {
1038 Dmsg1(110, "JobId=%u can_reserve_drive!=1\n", (int)jcr->JobId);
1042 dev->reserved_device++;
1043 Dmsg4(100, "JobId=%u Inc reserve=%d dev=%s %p\n", (int)jcr->JobId, dev->reserved_device,
1044 dev->print_name(), dev);
1045 dcr->reserved_device = true;
1054 * Returns: 1 if drive can be reserved
1055 * 0 if we should wait
1056 * -1 on error or impossibility
1058 static int can_reserve_drive(DCR *dcr, RCTX &rctx)
1060 DEVICE *dev = dcr->dev;
1061 JCR *jcr = dcr->jcr;
1063 Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
1065 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1066 rctx.autochanger_only, rctx.any_drive);
1068 /* setting any_drive overrides PreferMountedVols flag */
1069 if (!rctx.any_drive) {
1071 * When PreferMountedVols is set, we keep track of the
1072 * drive in use that has the least number of writers, then if
1073 * no unmounted drive is found, we try that drive. This
1074 * helps spread the load to the least used drives.
1076 if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
1077 Dmsg3(110, "OK dev=%s == low_drive=%s. JobId=%u\n",
1078 dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
1081 /* If he wants a free drive, but this one is busy, no go */
1082 if (!rctx.PreferMountedVols && dev->is_busy()) {
1083 /* Save least used drive */
1084 if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
1085 rctx.num_writers = dev->num_writers + dev->reserved_device;
1086 rctx.low_use_drive = dev;
1087 Dmsg3(110, "JobId=%u set low use drive=%s num_writers=%d\n",
1088 (int)jcr->JobId, dev->print_name(), rctx.num_writers);
1090 Dmsg2(110, "JobId=%u not low use num_writers=%d\n",
1091 (int)jcr->JobId, dev->num_writers+dev->reserved_device);
1093 Dmsg1(110, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
1094 Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"),
1095 jcr->JobId, dev->print_name());
1096 queue_reserve_message(jcr);
1100 /* Check for prefer mounted volumes */
1101 // if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
1102 if (rctx.PreferMountedVols && !dev->vol && dev->is_tape()) {
1103 Mmsg(jcr->errmsg, _("3606 JobId=%u prefers mounted drives, but drive %s has no Volume.\n"),
1104 jcr->JobId, dev->print_name());
1105 queue_reserve_message(jcr);
1106 Dmsg1(110, "failed: want mounted -- no vol JobId=%u\n", (uint32_t)jcr->JobId);
1107 return 0; /* No volume mounted */
1110 /* Check for exact Volume name match */
1111 /* ***FIXME*** use dev->vol.VolumeName */
1112 if (rctx.exact_match && rctx.have_volume &&
1113 strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
1114 Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"),
1115 jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName,
1117 queue_reserve_message(jcr);
1118 Dmsg3(110, "JobId=%u failed: Not exact match have=%s want=%s\n",
1119 (int)jcr->JobId, dev->VolHdr.VolumeName, rctx.VolumeName);
1124 /* Check for unused autochanger drive */
1125 /* ***FIXME*** use !dev->is_busy() */
1126 if (rctx.autochanger_only && dev->num_writers == 0 &&
1127 dev->VolHdr.VolumeName[0] == 0) {
1128 /* Device is available but not yet reserved, reserve it for us */
1129 Dmsg2(100, "OK Res Unused autochanger %s JobId=%u.\n",
1130 dev->print_name(), jcr->JobId);
1131 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1132 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1133 return 1; /* reserve drive */
1137 * Handle the case that there are no writers
1139 if (dev->num_writers == 0) {
1140 /* Now check if there are any reservations on the drive */
1141 if (dev->reserved_device) {
1142 /* Now check if we want the same Pool and pool type */
1143 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1144 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1145 /* OK, compatible device */
1146 Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
1147 dev->print_name(), jcr->JobId);
1150 /* Drive Pool not suitable for us */
1151 Mmsg(jcr->errmsg, _(
1152 "3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"),
1153 jcr->JobId, dcr->pool_name, dev->pool_name,
1154 dev->reserved_device, dev->print_name());
1155 queue_reserve_message(jcr);
1156 Dmsg3(110, "JobId=%u failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
1157 (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1158 return 0; /* wait */
1160 } else if (dev->can_append()) {
1161 /* Device in append mode, check if changing pool */
1162 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1163 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1164 Dmsg2(100, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
1165 dev->print_name(), jcr->JobId);
1166 /* OK, compatible device */
1169 /* Changing pool, unload old tape if any in drive */
1170 Dmsg1(100, "JobId=%u OK dev: num_writers=0, not reserved, pool change, unload changer\n",
1172 unload_autochanger(dcr, 0);
1175 /* Device is available but not yet reserved, reserve it for us */
1176 Dmsg2(100, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
1178 bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1179 bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1180 return 1; /* reserve drive */
1184 * Check if the device is in append mode with writers (i.e.
1185 * available if pool is the same).
1187 if (dev->can_append() || dev->num_writers > 0) {
1188 /* Yes, now check if we want the same Pool and pool type */
1189 if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1190 strcmp(dev->pool_type, dcr->pool_type) == 0) {
1191 Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
1192 dev->print_name(), jcr->JobId);
1193 /* OK, compatible device */
1196 /* Drive Pool not suitable for us */
1197 Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but has Pool=\"%s\" on drive %s.\n"),
1198 jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
1199 queue_reserve_message(jcr);
1200 Dmsg3(110, "JobId=%u failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
1201 (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1202 return 0; /* wait */
1205 Pmsg1(000, _("Logic error!!!! JobId=%u Should not get here.\n"), (int)jcr->JobId);
1206 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
1207 jcr->JobId, dev->print_name());
1208 queue_reserve_message(jcr);
1209 Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
1210 return -1; /* error, should not get here */
1212 Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"),
1213 jcr->JobId, dev->print_name());
1214 queue_reserve_message(jcr);
1215 Dmsg2(110, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
1220 * search_lock is already set on entering this routine
1222 static void queue_reserve_message(JCR *jcr)
1225 alist *msgs = jcr->reserve_msgs;
1232 * Look for duplicate message. If found, do
1235 for (i=msgs->size()-1; i >= 0; i--) {
1236 msg = (char *)msgs->get(i);
1240 /* Comparison based on 4 digit message number */
1241 if (strncmp(msg, jcr->errmsg, 4) == 0) {
1245 /* Message unique, so insert it */
1246 jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1250 * Send any reservation messages queued for this jcr
1252 void send_drive_reserve_messages(JCR *jcr, void sendit(const char *msg, int len, void *sarg), void *arg)
1258 lock_reservations();
1259 msgs = jcr->reserve_msgs;
1260 if (!msgs || msgs->size() == 0) {
1261 unlock_reservations();
1264 for (i=msgs->size()-1; i >= 0; i--) {
1265 msg = (char *)msgs->get(i);
1267 sendit(" ", 3, arg);
1268 sendit(msg, strlen(msg), arg);
1273 unlock_reservations();