X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Facquire.c;h=9823d4bb2c36ddbee23440b7eb5257bc7098e7de;hb=5c358307600ad7cd6983b8773f8d7dc1e7346c56;hp=67080def3d4b02395c38883f2bd06a292124421a;hpb=17350b711d777172e5ef8b1e865d979e92ff0a5c;p=bacula%2Fbacula diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 67080def3d..9823d4bb2c 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -38,7 +38,6 @@ /* Forward referenced functions */ static void attach_dcr_to_dev(DCR *dcr); -static bool is_tape_position_ok(JCR *jcr, DEVICE *dev); /********************************************************************* @@ -89,9 +88,15 @@ bool acquire_device_for_read(DCR *dcr) jcr->NumReadVolumes, jcr->CurReadVolume); goto get_out; /* should not happen */ } + /* + * Note, if we want to be able to work from a .bsr file only + * for disaster recovery, we must "simulate" reading the catalog + */ bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName)); + bstrncpy(dcr->VolCatInfo.VolCatName, vol->VolumeName, sizeof(dcr->VolCatInfo.VolCatName)); bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type)); dcr->VolCatInfo.Slot = vol->Slot; + dcr->VolCatInfo.InChanger = vol->Slot > 0; /* * If the MediaType requested for this volume is not the @@ -152,8 +157,10 @@ bool acquire_device_for_read(DCR *dcr) Dmsg1(50, "Media Type change. New device %s chosen.\n", dev->print_name()); bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName)); + bstrncpy(dcr->VolCatInfo.VolCatName, vol->VolumeName, sizeof(dcr->VolCatInfo.VolCatName)); bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type)); dcr->VolCatInfo.Slot = vol->Slot; + dcr->VolCatInfo.InChanger = vol->Slot > 0; bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name)); bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type)); } else { @@ -165,6 +172,19 @@ bool acquire_device_for_read(DCR *dcr) } } + if (reserve_volume(dcr, dcr->VolumeName) == NULL) { + Dmsg2(100, "Could not reserve volume %s on %s\n", dcr->VolumeName, + dcr->dev->print_name()); + Jmsg2(jcr, M_FATAL, 0, _("Could not reserve volume %s on %s\n"), dcr->VolumeName, + dcr->dev->print_name()); + goto get_out; + } + if (dev->vol && dev->vol->is_swapping()) { + dev->vol->set_slot(vol->Slot); + Dmsg3(100, "swapping: slot=%d Vol=%s dev=%s\n", dev->vol->get_slot(), + dev->vol->vol_name, dev->print_name()); + } + init_device_wait_timers(dcr); @@ -174,10 +194,11 @@ bool acquire_device_for_read(DCR *dcr) /* Volume info is always needed because of VolParts */ - Dmsg0(200, "dir_get_volume_info\n"); + Dmsg1(150, "dir_get_volume_info vol=%s\n", dcr->VolumeName); if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) { Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg); } + dev->set_load(); /* set to load volume */ for ( ;; ) { /* If not polling limit retries */ @@ -192,7 +213,7 @@ bool acquire_device_for_read(DCR *dcr) goto get_out; /* error return */ } - autoload_device(dcr, 0, NULL); + dcr->do_swapping(false/*is_writing*/); /* * This code ensures that the device is ready for @@ -201,8 +222,10 @@ bool acquire_device_for_read(DCR *dcr) */ Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName); if (dev->open(dcr, OPEN_READ_ONLY) < 0) { - Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"), - dev->print_name(), dcr->VolumeName, dev->bstrerror()); + if (!dev->poll) { + Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"), + dev->print_name(), dcr->VolumeName, dev->bstrerror()); + } goto default_path; } Dmsg1(50, "opened dev %s OK\n", dev->print_name()); @@ -236,6 +259,10 @@ bool acquire_device_for_read(DCR *dcr) } else { bstrncpy(dev->BadVolName, dev->VolHdr.VolumeName, sizeof(dev->BadVolName)); } + if (!unload_autochanger(dcr, -1)) { + /* at least free the device so we can re-open with correct volume */ + dev->close(); + } /* Fall through */ default: Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg); @@ -259,6 +286,16 @@ default_path: try_autochanger = false; continue; /* try reading volume mounted */ } + /* Try closing and re-opening */ + dev->close(); + dev->clear_unload(); + if (dev->open(dcr, OPEN_READ_ONLY) >= 0) { + continue; + } + if (!dev->poll) { + Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"), + dev->print_name(), dcr->VolumeName, dev->bstrerror()); + } } /* Mount a specific volume and no other */ @@ -314,6 +351,7 @@ DCR *acquire_device_for_append(DCR *dcr) DEVICE *dev = dcr->dev; JCR *jcr = dcr->jcr; bool ok = false; + bool have_vol = false; init_device_wait_timers(dcr); @@ -345,10 +383,10 @@ DCR *acquire_device_for_append(DCR *dcr) if (dev->num_writers == 0) { memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo)); } - if (!is_tape_position_ok(jcr, dev)) { - goto get_out; - } - } else { + have_vol = dcr->is_tape_position_ok(); + } + + if (!have_vol) { Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId); if (!dcr->mount_next_write_volume()) { if (!job_canceled(jcr)) { @@ -378,34 +416,6 @@ get_out: return ok ? dcr : NULL; } -/* - * Insanity check - * - * Check to see if the tape position as defined by the OS is - * the same as our concept. If it is not, we bail out, because - * it means the user has probably manually rewound the tape. - * Note, we check only if num_writers == 0, but this code will - * also work fine for any number of writers. If num_writers > 0, - * we probably should cancel all jobs using this device, or - * perhaps even abort the SD, or at a minimum, mark the tape - * in error. Another strategy with num_writers == 0, would be - * to rewind the tape and do a new eod() request. - */ -static bool is_tape_position_ok(JCR *jcr, DEVICE *dev) -{ - if (dev->is_tape() && dev->num_writers == 0) { - int32_t file = dev->get_os_tape_file(); - if (file >= 0 && file != (int32_t)dev->get_file()) { - Jmsg(jcr, M_FATAL, 0, _("Invalid tape position on volume \"%s\"" - " on device %s. Expected %d, got %d\n"), - dev->VolHdr.VolumeName, dev->print_name(), dev->get_file(), file); - return false; - } - } - return true; -} - - /* * This job is done, so release the device. From a Unix standpoint, * the device remains open. @@ -419,6 +429,7 @@ bool release_device(DCR *dcr) JCR *jcr = dcr->jcr; DEVICE *dev = dcr->dev; bool ok = true; + char tbuf[100]; /* lock only if not already locked by this thread */ if (!dcr->is_dev_locked()) { @@ -464,7 +475,7 @@ bool release_device(DCR *dcr) Dmsg2(200, "dir_update_vol_info. Release vol=%s dev=%s\n", dev->VolCatInfo.VolCatName, dev->print_name()); } - if (!dev->num_writers) { /* if no more writers */ + if (dev->num_writers == 0) { /* if not being used */ volume_unused(dcr); /* we obviously are not using the volume */ } } @@ -478,6 +489,10 @@ bool release_device(DCR *dcr) volume_unused(dcr); } unlock_volumes(); + Dmsg3(100, "%d writers, %d reserve, dev=%s\n", dev->num_writers, dev->num_reserved(), + dev->print_name()); + debug_list_volumes("acquire:release_device()"); + /* If no writers, close if file or !CAP_ALWAYS_OPEN */ if (dev->num_writers == 0 && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) { @@ -512,7 +527,8 @@ bool release_device(DCR *dcr) free_pool_memory(alert); } pthread_cond_broadcast(&dev->wait_next_vol); - Dmsg1(100, "JobId=%u broadcast wait_device_release\n", (uint32_t)jcr->JobId); + Dmsg2(100, "JobId=%u broadcast wait_device_release at %s\n", + (uint32_t)jcr->JobId, bstrftimes(tbuf, sizeof(tbuf), (utime_t)time(NULL))); pthread_cond_broadcast(&wait_device_release); dev->dunlock(); if (dcr->keep_dcr) {