SCSI tape data loss
Kern Sibbald
kern at sibbald.com
Tue Jun 3 08:05:19 PDT 2003
What is clear from the output is that the write()
is returning a -1 status. errno could possibly be 0,
in which case I set it to ENOSPC, if it is not 0
then it is ENOSPC judging by the error message that
is printed "Write error on device ...".
You may want to see more, but here is the basic code
that does the write:
if ((uint32_t)(stat=write(dev->fd, block->buf, (size_t)wlen)) !=
wlen) {
/* We should check for errno == ENOSPC, BUT many
* devices simply report EIO when it is full.
* with a little more thought we may be able to check
* capacity and distinguish real errors and EOT
* conditions. In any case, we probably want to
* simulate an End of Medium.
*/
clrerror_dev(dev, -1);
if (dev->dev_errno == 0) {
dev->dev_errno = ENOSPC; /* out of space */
}
Dmsg4(10, "=== Write error. size=%u rtn=%d errno=%d: ERR=%s\n",
wlen, stat, dev->dev_errno, strerror(dev->dev_errno));
if (stat == -1) {
Jmsg(jcr, M_ERROR, 0, _("Write error on device %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
} else {
Jmsg3(jcr, M_INFO, 0, _("End of medium on device %s. Write of
%u bytes got %d
dev->dev_name, wlen, stat);
}
block->write_failed = true;
dev->EndBlock = dev->block_num;
dev->EndFile = dev->file;
weof_dev(dev, 1); /* end the tape */
weof_dev(dev, 1); /* write second eof */
dev->state |= (ST_EOF | ST_EOT | ST_WEOT);
=======
clererror() does:
void
clrerror_dev(DEVICE *dev, int func)
{
char *msg = NULL;
dev->dev_errno = errno; /* save errno */
if (errno == EIO) {
dev->VolCatInfo.VolCatErrors++;
}
if (!(dev->state & ST_TAPE)) {
return;
}
if (errno == ENOTTY || errno == ENOSYS) { /* Function not implemented
*/
switch (func) {
case -1:
Emsg0(M_ABORT, 0, "Got ENOTTY on read/write!\n");
break;
case MTWEOF:
msg = "WTWEOF";
dev->capabilities &= ~CAP_EOF; /* turn off feature */
break;
#ifdef MTEOM
case MTEOM:
msg = "WTEOM";
dev->capabilities &= ~CAP_EOM; /* turn off feature */
break;
#endif
case MTFSF:
msg = "MTFSF";
dev->capabilities &= ~CAP_FSF; /* turn off feature */
break;
case MTBSF:
msg = "MTBSF";
dev->capabilities &= ~CAP_BSF; /* turn off feature */
break;
case MTFSR:
msg = "MTFSR";
dev->capabilities &= ~CAP_FSR; /* turn off feature */
break;
case MTBSR:
msg = "MTBSR";
dev->capabilities &= ~CAP_BSR; /* turn off feature */
break;
default:
msg = "Unknown";
break;
}
if (msg != NULL) {
dev->dev_errno = ENOSYS;
Mmsg1(&dev->errmsg, _("This device does not support %s.\n"),
msg);
Emsg0(M_ERROR, 0, dev->errmsg);
}
}
/* Found on Linux */
#ifdef MTIOCLRERR
{
struct mtop mt_com;
mt_com.mt_op = MTIOCLRERR;
mt_com.mt_count = 1;
/* Clear any error condition on the tape */
ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
Dmsg0(200, "Did MTIOCLRERR\n");
}
#endif
/* Typically on FreeBSD */
#ifdef MTIOCERRSTAT
{
/* Read and clear SCSI error status */
union mterrstat mt_errstat;
Pmsg2(000, "Doing MTIOCERRSTAT errno=%d ERR=%s\n", dev->dev_errno,
strerror(dev->dev_errno));
ioctl(dev->fd, MTIOCERRSTAT, (char *)&mt_errstat);
}
#endif
}
====
On Tue, 2003-06-03 at 16:34, Matthew Jacob wrote:
> The fact that you're getting ENOSPC means that you're getting to PEOT-
> past LEOT. I guess I need to see the Bacula source to see why LEOT is
> being missed. If you can build a kernel with CAMDEBUG and run
>
> camcontrol debug -I b:t:l
>
> (bus:target:lun for the tape) and rerun the test, you'll get boatloads
> of output, but an audit trail of what sastart and saerror are doing
> around the PEOT timeframe.
>
> There's other stuff here that I need to collect my thoughts on to mail
> about. This will happen later today.
>
> On Tue, 3 Jun 2003, Kern Sibbald wrote:
>
> > Hello,
> >
> > Dan has now re-run our test of writing to two tapes. In
> > this test, he told Bacula not to attempt to re-read the
> > last block written, so Bacula wrote until -1 with errno=ENOSPC
> > was returned, wrote two EOF marks then put up
> > the next volume.
> >
> > The results were the same (more or less) 12 blocks of
> > data were lost, which corresponds to the smaller size
> > of the restored file that was split across two tapes.
> >
> > These 12 blocks were also at the end of the tape.
> >
> > During the restore, Bacula reported the following:
> >
> > 03-Jun-2003 05:01 undef-sd: RestoreFiles.2003-06-03_04.36.59 Error:
> > Invalid block number. Expected 6060, got 6072
> >
> > and in Bacula's database, Bacula indicates that blocks
> > 0 to 6072 were written to the first tape. In fact, only
> > blocks 0 to 6071 were written to the first tape -- I
> > see that Bacula has included the failed block in its
> > count, which is wrong, but this doesn't change the results
> > at all though.
> >
> > Bottom line:
> >
> > Even when we eliminate the code that backs
> > up and re-reads the last block, we still see
> > the last 12 or 13 blocks being lost. They were
> > written by the program but are not physically
> > on the tape.
> >
> > Next step:
> >
> > Dan is now running a test where Bacula will stop
> > writing on the first tape before the EOM is reached.
> >
> > Best regards,
> >
> > Kern
> >
> >
> >
> >
> >
> >
More information about the freebsd-scsi
mailing list