General:
-Changes to 1.37.32:
+Changes to 1.37.34:
+03Aug03
+- Modify open() for tape so nonblocking really works.
+- Use fcntl() to reset blocking status rather than close()
+ and reopen the drive.
+- Make sure dev->open() is always called so that any change
+ in read/write permissions will occur.
+- Open drives initially in daemon in read-only mode.
+- Ensure that each time the VolHdr.VolumeName is zapped
+ or changed that free_volume() is called on the old name.
+
+Changes to 1.37.33:
03Aug03
- Require 5 arguments to mtx-changer except list and slots
- Turn -EPIPE status returns from bpipe to ETIME
- Do not term_dev() during initialization in SD if the device
could not be opened. In the case of a tape drive, there may
be no tape in the drive.
+
+Changes to 1.32.32:
02Aug05
- Correct PostgreSQL database scripts as suggested by a user.
- Add additional info to FATAL message generated when a device
* reading. If it is a file, it opens it.
* If it is a tape, it checks the volume name
*/
- for ( ; !dev->is_open(); ) {
- Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
- if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
- if (dev->dev_errno == EIO) { /* no tape loaded */
- Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed (EIO): ERR=%s\n"),
- dev->print_name(), dcr->VolumeName, strerror_dev(dev));
- goto default_path;
- }
-
+ Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
+ if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
+ if (dev->dev_errno == EIO) { /* no tape loaded */
+ Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed (EIO): ERR=%s\n"),
+ dev->print_name(), dcr->VolumeName, strerror_dev(dev));
+ goto default_path;
+ }
+
#ifdef xxx_needed
- /* If we have a dvd that requires mount,
- * we need to try to open the label, so the info can be reported
- * if a wrong volume has been mounted.
- */
- if (dev->is_dvd() && (dcr->VolCatInfo.VolCatParts > 0)) {
- break;
- }
+ /* If we have a dvd that requires mount,
+ * we need to try to open the label, so the info can be reported
+ * if a wrong volume has been mounted.
+ */
+ if (dev->is_dvd() && (dcr->VolCatInfo.VolCatParts > 0)) {
+ break;
+ }
#endif
-
- Jmsg3(jcr, M_FATAL, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
- dev->print_name(), dcr->VolumeName, strerror_dev(dev));
- goto get_out;
- }
- Dmsg1(100, "opened dev %s OK\n", dev->print_name());
+
+ Jmsg3(jcr, M_FATAL, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
+ dev->print_name(), dcr->VolumeName, strerror_dev(dev));
+ goto get_out;
}
+ Dmsg1(100, "opened dev %s OK\n", dev->print_name());
/* Read Volume Label */
if (VolName && *VolName && *VolName != '*') {
if (!same_label_names(VolName, &label[4])) {
char *p = &label[4];
- char *q = dev->VolHdr.VolumeName;
+ char *q;
+
+ free_volume(dev);
+ /* Store new Volume name */
+ q = dev->VolHdr.VolumeName;
for (int i=0; *p != ' ' && i < 6; i++) {
*q++ = *p++;
}
state &= ~(ST_LABEL|ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF);
label_type = B_BACULA_LABEL;
if (is_tape() || is_fifo()) {
- open_tape_device(omode);
+ open_tape_device(dcr, omode);
} else if (is_dvd()) {
Dmsg1(100, "call open_dvd_device mode=%s\n", mode_to_str(omode));
open_dvd_device(dcr, omode);
}
}
-void DEVICE::open_tape_device(int omode)
+/*
+ * If the flage open_nowait is set, which is the case
+ * when the daemon is initially trying to open the device,
+ * we open it with O_NONBLOCK set and O_RONLY, which will
+ * allow us to open normal Linux tape drives with no tape
+ * in the drive without blocking. We then immediately
+ * set blocking status so that if we read from the device they
+ * will be normal blocking reads.
+ *
+ * If later, we want to write on the device, it will be freed and
+ * reopened, but hopefully there will be a tape in the drive so
+ * we will not block.
+ */
+void DEVICE::open_tape_device(DCR *dcr, int omode)
{
int nonblocking = 0;;
file_size = 0;
tid = start_thread_timer(pthread_self(), timeout);
}
/* If busy retry each second for max_open_wait seconds */
-open_again:
- Dmsg1(500, "Try open %s\n", print_name());
+ Dmsg3(100, "Try open %s mode=%s nonblocking=%d\n", print_name(),
+ mode_to_str(omode), nonblocking);
/* Use system open() */
- while ((fd = ::open(dev_name, mode, MODE_RW+nonblocking)) < 0) {
+ while ((fd = ::open(dev_name, mode+nonblocking, MODE_RW)) < 0) {
berrno be;
- Dmsg2(500, "Open error errno=%d ERR=%s\n", errno, be.strerror());
+ Dmsg2(100, "Open error errno=%d ERR=%s\n", errno, be.strerror());
if (errno == EINTR || errno == EAGAIN) {
- Dmsg0(500, "Continue open\n");
+ Dmsg0(100, "Continue open\n");
continue;
}
/* Busy wait for specified time (default = 5 mins) */
/* IO error (no volume) try 10 times every 6 seconds */
if (errno == EIO && ioerrcnt-- > 0) {
bmicrosleep(5, 0);
- Dmsg0(500, "Continue open\n");
+ Dmsg0(100, "Continue open\n");
continue;
}
dev_errno = errno;
Emsg0(M_FATAL, 0, errmsg);
break;
}
- if (fd >= 0) {
- /* If opened in non-block mode, close it an open it normally */
+ /* Really an if, but we use a break for an error exit */
+ while (fd >= 0) {
+ /* If opened in non-block mode, make it block now */
if (nonblocking) {
+ int oflags;
nonblocking = 0;
- ::close(fd); /* use system close() */
- goto open_again;
+ /* Try to reset blocking */
+ if ((oflags = fcntl(fd, F_GETFL, 0)) < 0 ||
+ fcntl(fd, F_SETFL, oflags & ~O_NONBLOCK) < 0) {
+ berrno be;
+ Jmsg1(dcr->jcr, M_ERROR, 0, "fcntl error. ERR=%s\n", be.strerror());
+ ::close(fd); /* use system close() */
+ fd = -1;
+ break;
+ }
}
openmode = omode; /* save open mode */
Dmsg2(100, "openmode=%d %s\n", openmode, mode_to_str(openmode));
update_pos_dev(this); /* update position */
set_os_device_parameters(this); /* do system dependent stuff */
Dmsg0(500, "Open OK\n");
+ break;
}
/* Stop any open() timer we started */
if (tid) {
dev->part_start = 0;
dev->EndFile = dev->EndBlock = 0;
memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo));
+ free_volume(dev);
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
if (dev->tid) {
stop_thread_timer(dev->tid);
int mode; /* read/write modes */
int openmode; /* parameter passed to open_dev (useful to reopen the device) */
bool autoselect; /* Autoselect in autochanger */
- bool open_nowait; /* If set, don t wait on open */
+ bool open_nowait; /* If set, don't wait on open */
int label_type; /* Bacula/ANSI/IBM label types */
uint32_t drive_index; /* Autochanger drive index (base 0) */
int32_t Slot; /* Slot currently in drive (base 1) */
private:
void set_mode(int omode); /* in dev.c */
- void open_tape_device(int omode); /* in dev.c */
+ void open_tape_device(DCR *dcr, int omode); /* in dev.c */
void open_file_device(int omode); /* in dev.c */
void open_dvd_device(DCR *dcr, int omode); /* in dev.c */
if (dev_cap(dev, CAP_STREAM)) {
mode = OPEN_WRITE_ONLY;
} else {
- mode = OPEN_READ_WRITE;
+ mode = OPEN_READ_ONLY;
}
Dmsg0(129, "Opening device.\n");
dev->open_nowait = true;
}
/* Ensure that the device is open -- autoload_device() closes it */
- for ( ; !dev->is_open(); ) {
- if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
- bnet_fsend(dir, _("3910 Unable to open device %s: ERR=%s\n"),
- dev->print_name(), dev->strerror());
- return false;
- }
+ if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
+ bnet_fsend(dir, _("3910 Unable to open device %s: ERR=%s\n"),
+ dev->print_name(), dev->strerror());
+ return false;
}
return true;
}
Dmsg1(100, "Label type=%d\n", dev->label_type);
if (!rewind_dev(dev)) {
+ free_volume(dev);
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
Dmsg2(30, "Bad status on %s from rewind: ERR=%s\n", dev->print_name(), strerror_dev(dev));
if (!forge_on) {
return true;
bail_out:
+ free_volume(dev);
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
dev->clear_append(); /* remove append since this is PRE_LABEL */
return false;
ASSERT(dev != NULL);
+ free_volume(dev); /* release any old volume */
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id));
/* */
#undef VERSION
-#define VERSION "1.37.33"
+#define VERSION "1.37.34"
#define BDATE "03 August 2005"
#define LSMDATE "03Aug05"