This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
- version 2 as ammended with additional clauses defined in the
+ version 2 as amended with additional clauses defined in the
file LICENSE in the main source directory.
This program is distributed in the hope that it will be useful,
JCR *jcr = dcr->jcr;
DEV_BLOCK *block = dcr->block;
- Dmsg0(100, "Enter mount_next_volume()\n");
+ Dmsg1(150, "Enter mount_next_volume(release=%d)\n", release);
init_device_wait_timers(dcr);
* Volume, ...)
*/
mount_next_vol:
+ Dmsg1(150, "mount_next_vol retry=%d\n", retry);
/* Ignore retry if this is poll request */
if (!dev->poll && retry++ > 4) {
/* Last ditch effort before giving up, force operator to respond */
}
recycle = false;
if (release) {
- Dmsg0(100, "mount_next_volume release=1\n");
+ Dmsg0(150, "mount_next_volume release=1\n");
release_volume(dcr);
ask = true; /* ask operator to mount tape */
}
if (job_canceled(jcr)) {
return false;
}
- Dmsg3(100, "After find_next_append. Vol=%s Slot=%d Parts=%d\n",
+ Dmsg3(150, "After find_next_append. Vol=%s Slot=%d Parts=%d\n",
dcr->VolCatInfo.VolCatName, dcr->VolCatInfo.Slot, dcr->VolCatInfo.VolCatParts);
- dev->num_parts = dcr->VolCatInfo.VolCatParts;
-
/*
* Get next volume and ready it for append
* This code ensures that the device is ready for
autochanger = false;
dcr->VolCatInfo.Slot = 0;
}
- Dmsg1(100, "autoload_dev returns %d\n", autochanger);
+ Dmsg1(200, "autoload_dev returns %d\n", autochanger);
/*
* If we autochanged to correct Volume or (we have not just
* released the Volume AND we can automount) we go ahead
* we will err, recurse and ask the operator the next time.
*/
if (!release && dev->is_tape() && dev_cap(dev, CAP_AUTOMOUNT)) {
+ Dmsg0(150, "(1)Ask=0\n");
ask = false; /* don't ask SYSOP this time */
}
/* Don't ask if not removable */
if (!dev_cap(dev, CAP_REM)) {
+ Dmsg0(150, "(2)Ask=0\n");
ask = false;
}
- Dmsg2(100, "Ask=%d autochanger=%d\n", ask, autochanger);
+ Dmsg2(150, "Ask=%d autochanger=%d\n", ask, autochanger);
release = true; /* release next time if we "recurse" */
if (ask && !dir_ask_sysop_to_mount_volume(dcr)) {
- Dmsg0(100, "Error return ask_sysop ...\n");
+ Dmsg0(150, "Error return ask_sysop ...\n");
return false; /* error return */
}
if (job_canceled(jcr)) {
return false;
}
- Dmsg1(100, "want vol=%s\n", dcr->VolumeName);
+ Dmsg1(150, "want vol=%s\n", dcr->VolumeName);
if (dev->poll && dev_cap(dev, CAP_CLOSEONPOLL)) {
force_close_device(dev);
}
/* Ensure the device is open */
- /* If we have a dvd that requires mount, we first want to guess
- * which Volume is loaded, so we continue (if the wrong device is
- * loaded, open_device just below would fail.
- */
- if (!dev->is_dvd()) {
- if (!open_device(dcr)) {
- if (dev->poll) {
- goto mount_next_vol;
- } else {
- return false;
- }
+ if (!open_device(dcr)) {
+ /* If DVD, ignore the error, very often you cannot open the device
+ * (when there is no DVD, or when the one inserted is a wrong one) */
+ if ((dev->poll) || (dev->is_dvd())) {
+ goto mount_next_vol;
+ } else {
+ return false;
}
- } else {
- /*
- * Just copy the VolCatName in the device resource
- * (usually done by open_dev).
- * It is necessary so we can open the real files later.
- */
- bstrncpy(dev->VolCatInfo.VolCatName, dcr->VolCatInfo.VolCatName, sizeof(dev->VolCatInfo.VolCatName));
}
/*
vol_label_status = VOL_OK;
create_volume_label(dev, dcr->VolumeName, "Default");
dev->VolHdr.LabelType = PRE_LABEL;
- } else if (dev->is_dvd()) {
- vol_label_status = read_dvd_volume_label(dcr, /*write*/true);
} else {
vol_label_status = read_dev_volume_label(dcr);
}
return false;
}
- Dmsg2(100, "Want dirVol=%s dirStat=%s\n", dcr->VolumeName,
+ Dmsg2(150, "Want dirVol=%s dirStat=%s\n", dcr->VolumeName,
dcr->VolCatInfo.VolCatStatus);
/*
* At this point, dev->VolCatInfo has what is in the drive, if anything,
*/
switch (vol_label_status) {
case VOL_OK:
- Dmsg1(100, "Vol OK name=%s\n", dcr->VolumeName);
+ Dmsg1(150, "Vol OK name=%s\n", dcr->VolumeName);
memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0;
break; /* got a Volume */
goto mount_next_vol;
}
- Dmsg1(100, "Vol NAME Error Name=%s\n", dcr->VolumeName);
+ Dmsg1(150, "Vol NAME Error Name=%s\n", dcr->VolumeName);
/* If polling and got a previous bad name, ignore it */
if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolumeName) == 0) {
ask = true;
/* Check if this is a valid Volume in the pool */
bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) {
- /* Restore desired volume name, note device info out of sync */
- /* This gets the info regardless of the Pool */
+ /* Saved bad volume name */
+ bstrncpy(dev->BadVolName, dev->VolHdr.VolumeName, sizeof(dev->BadVolName));
+ Jmsg(jcr, M_WARNING, 0, _("Director wanted Volume \"%s\" for device %s.\n"
+ " Current Volume \"%s\" not acceptable because:\n"
+ " %s"),
+ VolCatInfo.VolCatName, dev->print_name(),
+ dev->VolHdr.VolumeName, jcr->dir_bsock->msg);
+ /* This gets the info regardless of the Pool so we can change chgr status */
bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
- if (autochanger && dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
+ if (autochanger && !dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
mark_volume_not_inchanger(dcr);
}
+ /* Restore original info */
memcpy(&dev->VolCatInfo, &devVolCatInfo, sizeof(dev->VolCatInfo));
- bstrncpy(dev->BadVolName, dev->VolHdr.VolumeName, sizeof(dev->BadVolName));
- Jmsg(jcr, M_WARNING, 0, _("Director wanted Volume \"%s\".\n"
- " Current Volume \"%s\" not acceptable because:\n"
- " %s"),
- VolCatInfo.VolCatName, dev->VolHdr.VolumeName,
- jcr->dir_bsock->msg);
ask = true;
goto mount_next_vol;
}
/* This was not the volume we expected, but it is OK with
* the Director, so use it.
*/
- Dmsg1(100, "want new name=%s\n", dcr->VolumeName);
+ Dmsg1(150, "want new name=%s\n", dcr->VolumeName);
memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0;
break; /* got a Volume */
/*
* At this point, we assume we have a blank tape mounted.
*/
- case VOL_NO_LABEL:
case VOL_IO_ERROR:
+ if (dev->is_dvd()) {
+ Jmsg(jcr, M_FATAL, 0, "%s", jcr->errmsg);
+ mark_volume_in_error(dcr);
+ return false; /* we could not write on DVD */
+ }
+ /* Fall through wanted */
+ case VOL_NO_LABEL:
/*
* If permitted, we label the device, make sure we can do
* it by checking that the VolCatBytes is zero => not labeled,
if (dev_cap(dev, CAP_LABEL) && (dcr->VolCatInfo.VolCatBytes == 0 ||
(!dev->is_tape() && strcmp(dcr->VolCatInfo.VolCatStatus,
"Recycle") == 0))) {
- Dmsg0(100, "Create volume label\n");
+ Dmsg0(150, "Create volume label\n");
/* Create a new Volume label and write it to the device */
if (!write_new_volume_label_to_dev(dcr, dcr->VolumeName,
dcr->pool_name)) {
- Dmsg0(100, "!write_vol_label\n");
+ Dmsg0(150, "!write_vol_label\n");
mark_volume_in_error(dcr);
goto mount_next_vol;
}
- Dmsg0(100, "dir_update_vol_info. Set Append\n");
+ Dmsg0(150, "dir_update_vol_info. Set Append\n");
/* Copy Director's info into the device info */
memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
if (!dir_update_volume_info(dcr, true)) { /* indicate tape labeled */
dcr->VolumeName, dev->print_name());
goto read_volume; /* read label we just wrote */
}
+ if (!dev_cap(dev, CAP_LABEL) && dcr->VolCatInfo.VolCatBytes == 0) {
+ Jmsg(jcr, M_INFO, 0, _("Warning device %s not configured to autolabel Volumes.\n"),
+ dev->print_name());
+ }
/* If not removable, Volume is broken */
if (!dev_cap(dev, CAP_REM)) {
Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
/* NOTE! Fall-through wanted. */
case VOL_NO_MEDIA:
default:
+ Dmsg0(200, "VOL_NO_MEDIA or default.\n");
/* Send error message */
if (!dev->poll) {
- Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
} else {
Dmsg1(200, "Msg suppressed by poll: %s\n", jcr->errmsg);
}
}
}
dev->VolCatInfo.VolCatMounts++; /* Update mounts */
- Dmsg1(100, "update volinfo mounts=%d\n", dev->VolCatInfo.VolCatMounts);
+ Dmsg1(150, "update volinfo mounts=%d\n", dev->VolCatInfo.VolCatMounts);
if (!dir_update_volume_info(dcr, false)) {
return false;
}
+
+ /*
+ * DVD : check if the last part was removed or truncated, or if a written
+ * part was overwritten.
+ * We need to do it after dir_update_volume_info, so we have the EndBlock
+ * info. (nb: I don't understand why VolCatFiles is set (used to check
+ * tape file number), but not EndBlock)
+ * Maybe could it be changed "dev->is_file()" (would remove the fixme above)
+ *
+ * Disabled: I had problems with this code...
+ * (maybe is it related to the seek bug ?)
+ */
+#ifdef xxx
+ if (dev->is_dvd()) {
+ Dmsg2(150, "DVD/File sanity check addr=%u vs endblock=%u\n", (unsigned int)dev->file_addr, (unsigned int)dev->VolCatInfo.EndBlock);
+ if (dev->file_addr == dev->VolCatInfo.EndBlock+1) {
+ Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\" at file address=%u.\n"),
+ dcr->VolumeName, (unsigned int)dev->file_addr);
+ }
+ else {
+ Jmsg(jcr, M_ERROR, 0, _("I cannot write on Volume \"%s\" because:\n"
+ "The EOD file address is wrong: Volume file address=%u != Catalog Endblock=%u(+1)\n"
+ "You probably removed DVD last part in spool directory.\n"),
+ dcr->VolumeName, (unsigned int)dev->file_addr, (unsigned int)dev->VolCatInfo.EndBlock);
+ mark_volume_in_error(dcr);
+ goto mount_next_vol;
+ }
+ }
+#endif
+
/* Return an empty block */
empty_block(block); /* we used it for reading so set for write */
}
dev->set_append();
- Dmsg0(100, "set APPEND, normal return from read_dev_for_append\n");
+ Dmsg0(150, "set APPEND, normal return from read_dev_for_append\n");
return true;
}
dcr->VolumeName);
memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus));
- Dmsg0(100, "dir_update_vol_info. Set Error.\n");
+ Dmsg0(150, "dir_update_vol_info. Set Error.\n");
dir_update_volume_info(dcr, false);
}
JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
if (dcr->WroteVol) {
- Jmsg0(jcr, M_ERROR, 0, "Hey!!!!! WroteVol non-zero !!!!!\n");
+ Jmsg0(jcr, M_ERROR, 0, _("Hey!!!!! WroteVol non-zero !!!!!\n"));
Dmsg0(190, "Hey!!!!! WroteVol non-zero !!!!!\n");
}
/*
if (dev->is_open()) {
offline_or_rewind_dev(dev);
}
- Dmsg0(190, "===== release_volume ---");
+ Dmsg0(190, "release_volume\n");
}
/*
close_device(dev);
dev->clear_read();
if (!acquire_device_for_read(dcr)) {
- Jmsg2(jcr, M_FATAL, 0, "Cannot open Dev=%s, Vol=%s\n", dev->print_name(),
+ Jmsg2(jcr, M_FATAL, 0, _("Cannot open Dev=%s, Vol=%s\n"), dev->print_name(),
dcr->VolumeName);
return false;
}