/* Forward referenced functions */
static void attach_dcr_to_dev(DCR *dcr);
-static bool is_tape_position_ok(JCR *jcr, DEVICE *dev);
/*********************************************************************
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
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 {
}
}
+ 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);
/* 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 */
goto get_out; /* error return */
}
- dcr->do_swapping();
-
- autoload_device(dcr, 0, NULL);
+ dcr->do_swapping(false/*is_writing*/);
/*
* This code ensures that the device is ready for
*/
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());
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 */
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
bool ok = false;
+ bool have_vol = false;
init_device_wait_timers(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)) {
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.
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()) {
Dmsg2(200, "dir_update_vol_info. Release vol=%s dev=%s\n",
dev->VolCatInfo.VolCatName, dev->print_name());
}
- if (!dev->is_busy()) { /* if not being used */
+ if (dev->num_writers == 0) { /* if not being used */
volume_unused(dcr); /* we obviously are not using the volume */
}
}
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))) {
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) {