/* Forward referenced functions */
static void attach_dcr_to_dev(DCR *dcr);
-static bool is_suitable_volume_mounted(DCR *dcr);
+static bool is_tape_position_ok(JCR *jcr, DEVICE *dev);
/*********************************************************************
/* Mount a specific volume and no other */
Dmsg0(200, "calling dir_ask_sysop\n");
- if (!dir_ask_sysop_to_mount_volume(dcr)) {
+ if (!dir_ask_sysop_to_mount_volume(dcr, ST_READ)) {
goto get_out; /* error return */
}
try_autochanger = true; /* permit using autochanger again */
*/
DCR *acquire_device_for_append(DCR *dcr)
{
- bool do_mount = false;
- bool release = false;
- bool have_vol;
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
* have_vol defines whether or not mount_next_write_volume should
* ask the Director again about what Volume to use.
*/
- have_vol = is_suitable_volume_mounted(dcr);
- if (dev->can_append()) {
+ if (dev->can_append() && dcr->is_suitable_volume_mounted() &&
+ strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") != 0) {
Dmsg0(190, "device already in append.\n");
/*
- * Device already in append mode
- *
- * Check if we have the right Volume mounted
- * OK if current volume info OK
- * OK if next volume matches current volume
- * otherwise mount desired volume obtained from
- * dir_find_next_appendable_volume
- * dev->VolHdr.VolumeName is what is in the drive
- * dcr->VolumeName is what we pass into the routines, or
- * get back from the subroutines.
+ * At this point, the correct tape is already mounted, so
+ * we do not need to do mount_next_write_volume(), unless
+ * we need to recycle the tape.
*/
- if (!have_vol &&
- !(dir_find_next_appendable_volume(dcr) &&
- strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
- /* Wrong tape mounted, release it, then fall through to get correct one */
- Dmsg0(50, "Wrong tape mounted, release and try mount.\n");
- release = true;
- do_mount = true;
- } else {
- /*
- * At this point, the correct tape is already mounted, so
- * we do not need to do mount_next_write_volume(), unless
- * we need to recycle the tape.
- */
- do_mount = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
- Dmsg2(190, "jid=%u Correct tape mounted. recycle=%d\n",
- (uint32_t)jcr->JobId, do_mount);
-#ifdef xxx
- if (do_mount && dev->num_writers != 0) {
- Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
- " on device %s because it is in use by another job.\n"),
- dev->VolHdr.VolumeName, dev->print_name());
- goto get_out;
- }
-#endif
- if (dev->num_writers == 0) {
- memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
- }
-
- /*
- * 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.
- */
- 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);
- goto get_out;
- }
- }
- }
+ if (dev->num_writers == 0) {
+ memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
+ }
+ if (!is_tape_position_ok(jcr, dev)) {
+ goto get_out;
+ }
} else {
- /* Not already in append mode, so mount the device */
- Dmsg2(190, "jid=%u Not in append mode, try mount have_vol=%d\n",
- (uint32_t)jcr->JobId, have_vol);
-
- ASSERT(dev->num_writers == 0);
- do_mount = true;
- }
-
- if (do_mount || !have_vol) {
Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId);
- bool mounted = mount_next_write_volume(dcr, have_vol, release);
- if (!mounted) {
+ 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"),
return NULL;
}
-
-static bool is_suitable_volume_mounted(DCR *dcr)
+/*
+ * 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)
{
- DEVICE *dev = dcr->dev;
-
- /* Volume mounted? */
- if (dev->VolHdr.VolumeName[0] == 0) {
- return false; /* no */
+ 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;
+ }
}
- bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
- return dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE);
+ return true;
}
+
/*
* This job is done, so release the device. From a Unix standpoint,
* the device remains open.
if (!dcr->is_dev_locked()) {
dev->r_dlock();
}
+ lock_volumes();
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 */
dev->clear_read(); /* clear read bit */
Dmsg0(100, "dir_update_vol_info. Release0\n");
dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
+ volume_unused(dcr);
} else if (dev->num_writers > 0) {
/*
dev->num_writers--;
Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
if (dev->is_labeled()) {
- Dmsg0(100, "dir_create_jobmedia_record. Release\n");
+ Dmsg2(200, "dir_create_jobmedia. Release vol=%s dev=%s\n",
+ dev->VolCatInfo.VolCatName, dev->print_name());
if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
dcr->VolCatInfo.VolCatName, jcr->Job);
}
- /* If no more writers, write an EOF */
+ /* If no more writers, and no errors, and wrote something, write an EOF */
if (!dev->num_writers && dev->can_write() && dev->block_num > 0) {
dev->weof(1);
write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
if (!dev->at_weot()) {
dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
/* Note! do volume update before close, which zaps VolCatInfo */
- Dmsg0(100, "dir_update_vol_info. Release0\n");
dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
+ 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 */
+ volume_unused(dcr); /* we obviously are not using the volume */
}
}
* has failed, since the device is not in read mode and
* there are no writers. It was probably reserved.
*/
+ volume_unused(dcr);
}
+ unlock_volumes();
/* If no writers, close if file or !CAP_ALWAYS_OPEN */
if (dev->num_writers == 0 && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
void detach_dcr_from_dev(DCR *dcr)
{
DEVICE *dev = dcr->dev;
- Dmsg1(500, "JobId=%u enter detach_dcr_from_dev\n", (uint32_t)dcr->jcr->JobId);
+ Dmsg0(500, "Enter detach_dcr_from_dev\n"); /* jcr is NULL in some cases */
/* Detach this dcr only if attached */
if (dcr->attached_to_dev && dev) {