X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Facquire.c;h=9823d4bb2c36ddbee23440b7eb5257bc7098e7de;hb=cfc2aa18dbf9afb34902a14473152f388836538d;hp=58ed74db62c0d7486f2ed562f21952065fc5b996;hpb=53d4abaabf33a4bbbff72ad841e616b573e5dd54;p=bacula%2Fbacula diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 58ed74db62..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 */ @@ -286,11 +323,7 @@ default_path: get_out: dev->dlock(); - if (dcr && dcr->reserved_device) { - dev->reserved_device--; - Dmsg2(50, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); - dcr->reserved_device = false; - } + dcr->clear_reserved(); /* * Normally we are blocked, but in at least one error case above * we are not blocked because we unsuccessfully tried changing @@ -317,6 +350,8 @@ 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); @@ -348,18 +383,18 @@ 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)) { /* Reduce "noise" -- don't print if job canceled */ Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"), dev->print_name()); - Dmsg2(200, "jid=%u Could not ready device %s for append.\n", - (uint32_t)jcr->JobId, dev->print_name()); + Dmsg1(200, "Could not ready device %s for append.\n", + dev->print_name()); } goto get_out; } @@ -372,59 +407,15 @@ DCR *acquire_device_for_append(DCR *dcr) } dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */ dir_update_volume_info(dcr, false, false); /* send Volume info to Director */ - dev->dlock(); - if (dcr->reserved_device) { - dev->reserved_device--; - Dmsg3(100, "jid=%u Dec reserve=%d dev=%s\n", (uint32_t)jcr->JobId, - dev->reserved_device, dev->print_name()); - dcr->reserved_device = false; - } - dev->dunblock(DEV_LOCKED); - return dcr; + ok = true; -/* - * Error return - */ get_out: dev->dlock(); - if (dcr->reserved_device) { - dev->reserved_device--; - Dmsg3(100, "jid=%u Dec reserve=%d dev=%s\n", (uint32_t)jcr->JobId, - dev->reserved_device, dev->print_name()); - dcr->reserved_device = false; - } + dcr->clear_reserved(); dev->dunblock(DEV_LOCKED); - return NULL; + 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. @@ -438,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()) { @@ -447,11 +439,7 @@ bool release_device(DCR *dcr) Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk"); /* if device is reserved, job never started, so release the reserve here */ - if (dcr->reserved_device) { - dev->reserved_device--; - Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); - dcr->reserved_device = false; - } + dcr->clear_reserved(); if (dev->can_read()) { dev->clear_read(); /* clear read bit */ @@ -487,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 */ } } @@ -501,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))) { @@ -535,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) { @@ -664,7 +657,7 @@ void detach_dcr_from_dev(DCR *dcr) /* Detach this dcr only if attached */ if (dcr->attached_to_dev && dev) { dev->dlock(); - unreserve_device(dcr); + dcr->unreserve_device(); dcr->dev->attached_dcrs->remove(dcr); /* detach dcr from device */ dcr->attached_to_dev = false; // remove_dcr_from_dcrs(dcr); /* remove dcr from jcr list */