Skip to content

Commit

Permalink
stored: do not treat read error as EoT by default
Browse files Browse the repository at this point in the history
Fixes #1034: Read error on tape may be misinterpreted as end-of-tape
Previously stored treated a read-error immediately
following an end-of-file mark on a tape as end-of-tape
instead of an error.
This patch makes stored raise an error in this case,
but allows to switch back to the previous behaviour on
a per-device basis using the new configuration option
"Eof On Error Is Eot".
  • Loading branch information
arogge committed Jan 15, 2019
1 parent 1ad6542 commit 2be266a
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 80 deletions.
2 changes: 1 addition & 1 deletion src/stored/backends/generic_tape_device.c
Expand Up @@ -1402,7 +1402,7 @@ bool generic_tape_device::reposition(DCR *dcr, uint32_t rfile, uint32_t rblock)
return fsr(rblock-block_num);
} else {
while (rblock > block_num) {
if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
if (Ok != dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
berrno be;
dev_errno = errno;
Dmsg2(30, "Failed to find requested block on %s: ERR=%s", prt_name, be.bstrerror());
Expand Down
41 changes: 21 additions & 20 deletions src/stored/block.c
Expand Up @@ -772,7 +772,7 @@ static void reread_last_block(DCR *dcr)
* Note, this can destroy dev->errmsg
*/
dcr->block = lblock;
if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
if (Ok != dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
Jmsg(jcr, M_ERROR, 0, _("Re-read last block at EOT failed. ERR=%s"), dev->errmsg);
} else {
/*
Expand Down Expand Up @@ -923,24 +923,24 @@ static bool do_new_file_bookkeeping(DCR *dcr)
/**
* Read block with locking
*/
bool DCR::read_block_from_device(bool check_block_numbers)
ReadStatus DCR::read_block_from_device(bool check_block_numbers)
{
bool ok;
ReadStatus status;

Dmsg0(250, "Enter read_block_from_device\n");
dev->rLock();
ok = read_block_from_dev(check_block_numbers);
status = read_block_from_dev(check_block_numbers);
dev->Unlock();
Dmsg0(250, "Leave read_block_from_device\n");
return ok;
return status;
}

/**
* Read the next block into the block structure and unserialize
* the block header. For a file, the block may be partially
* or completely in the current buffer.
*/
bool DCR::read_block_from_dev(bool check_block_numbers)
ReadStatus DCR::read_block_from_dev(bool check_block_numbers)
{
ssize_t status;
int looping;
Expand All @@ -950,13 +950,13 @@ bool DCR::read_block_from_dev(bool check_block_numbers)
if (job_canceled(jcr)) {
Mmsg(dev->errmsg, _("Job failed or canceled.\n"));
block->read_len = 0;
return false;
return Error;
}

if (dev->at_eot()) {
Mmsg(dev->errmsg, _("Attempt to read past end of tape or file.\n"));
block->read_len = 0;
return false;
return EndOfTape;
}
looping = 0;
Dmsg1(250, "Full read in read_block_from_device() len=%d\n",
Expand All @@ -967,7 +967,7 @@ bool DCR::read_block_from_dev(bool check_block_numbers)
dev->fd(), dev->file, dev->block_num, dev->print_name());
Jmsg(dcr->jcr, M_WARNING, 0, "%s", dev->errmsg);
block->read_len = 0;
return false;
return Error;
}

reread:
Expand All @@ -977,7 +977,7 @@ bool DCR::read_block_from_dev(bool check_block_numbers)
dev->print_name());
Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
block->read_len = 0;
return false;
return Error;
}

retry = 0;
Expand Down Expand Up @@ -1008,10 +1008,11 @@ bool DCR::read_block_from_dev(bool check_block_numbers)
generate_plugin_event(jcr, bsdEventReadError, dcr);

Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
if (dev->at_eof()) { /* EOF just seen? */
dev->set_eot(); /* yes, error => EOT */
if (device->eof_on_error_is_eot && dev->at_eof()) { /* EOF just seen? */
dev->set_eot(); /* yes, error => EOT */
return EndOfTape;
}
return false;
return Error;
}

Dmsg3(250, "Read device got %d bytes at %u:%u\n", status,
Expand All @@ -1024,10 +1025,10 @@ bool DCR::read_block_from_dev(bool check_block_numbers)
dev->file, dev->block_num, dev->print_name());
if (dev->at_eof()) { /* EOF already read? */
dev->set_eot(); /* yes, 2 EOFs => EOT */
return 0;
return EndOfTape;
}
dev->set_ateof();
return false; /* return eof */
return EndOfFile;
}

/*
Expand All @@ -1051,7 +1052,7 @@ bool DCR::read_block_from_dev(bool check_block_numbers)
dev->set_short_block();
block->read_len = block->binbuf = 0;
Dmsg2(200, "set block=%p binbuf=%d\n", block, block->binbuf);
return false; /* return error */
return Error;
}

// BlockNumber = block->BlockNumber + 1;
Expand All @@ -1061,7 +1062,7 @@ bool DCR::read_block_from_dev(bool check_block_numbers)
dev->file_size += block->read_len;
goto reread;
}
return false;
return Error;
}

/*
Expand All @@ -1084,7 +1085,7 @@ bool DCR::read_block_from_dev(bool check_block_numbers)
Mmsg(dev->errmsg, "%s", dev->bstrerror());
Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
block->read_len = 0;
return false;
return Error;
}
} else {
Dmsg0(250, "Seek to beginning of block for reread.\n");
Expand Down Expand Up @@ -1115,7 +1116,7 @@ bool DCR::read_block_from_dev(bool check_block_numbers)
Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
dev->set_short_block();
block->read_len = block->binbuf = 0;
return false; /* return error */
return Error;
}

dev->clear_short_block();
Expand Down Expand Up @@ -1177,5 +1178,5 @@ bool DCR::read_block_from_dev(bool check_block_numbers)
Dmsg2(250, "Exit read_block read_len=%d block_len=%d\n",
block->read_len, block->block_len);
block->block_read = true;
return true;
return Ok;
}
31 changes: 18 additions & 13 deletions src/stored/bls.c
Expand Up @@ -291,13 +291,15 @@ static void do_blocks(char *infname)
DEV_BLOCK *block = dcr->block;
char buf1[100], buf2[100];
for ( ;; ) {
if (!dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
Dmsg1(100, "!read_block(): ERR=%s\n", dev->bstrerror());
if (dev->at_eot()) {
switch(dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
case Ok:
// no special handling required
break;
case EndOfTape:
if (!mount_next_read_volume(dcr)) {
Jmsg(jcr, M_INFO, 0, _("Got EOM at file %u on device %s, Volume \"%s\"\n"),
dev->file, dev->print_name(), dcr->VolumeName);
break;
return;
}
/* Read and discard Volume label */
DEV_RECORD *record;
Expand All @@ -307,19 +309,22 @@ static void do_blocks(char *infname)
get_session_record(dev, record, &sessrec);
free_record(record);
Jmsg(jcr, M_INFO, 0, _("Mounted Volume \"%s\".\n"), dcr->VolumeName);
} else if (dev->at_eof()) {
break;
case EndOfFile:
Jmsg(jcr, M_INFO, 0, _("End of file %u on device %s, Volume \"%s\"\n"),
dev->file, dev->print_name(), dcr->VolumeName);
Dmsg0(20, "read_record got eof. try again\n");
continue;
} else if (dev->is_short_block()) {
Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg);
continue;
} else {
/* I/O error */
display_tape_error_status(jcr, dev);
break;
}
default:
Dmsg1(100, "!read_block(): ERR=%s\n", dev->bstrerror());
if (dev->is_short_block()) {
Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg);
continue;
} else {
/* I/O error */
display_tape_error_status(jcr, dev);
return;
}
}
if (!match_bsr_block(bsr, block)) {
Dmsg5(100, "reject Blk=%u blen=%u bVer=%d SessId=%u SessTim=%u\n",
Expand Down
52 changes: 27 additions & 25 deletions src/stored/btape.c
Expand Up @@ -863,7 +863,7 @@ static bool re_read_block_test()
goto bail_out;
}
Pmsg0(0, _("Backspace record OK.\n"));
if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
if (Ok != dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
berrno be;
Pmsg1(0, _("Read block failed! ERR=%s\n"), be.bstrerror(dev->dev_errno));
goto bail_out;
Expand Down Expand Up @@ -1236,7 +1236,7 @@ static bool write_read_test()
*/
for (uint32_t i = 1; i <= 2 * num_recs; i++) {
read_again:
if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
if (Ok != dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
berrno be;
if (dev->at_eof()) {
Pmsg0(-1, _("Got EOF on tape.\n"));
Expand Down Expand Up @@ -1354,7 +1354,7 @@ static bool position_test()
goto bail_out;
}
read_again:
if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
if (Ok != dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
berrno be;
if (dev->at_eof()) {
Pmsg0(-1, _("Got EOF on tape.\n"));
Expand Down Expand Up @@ -2066,9 +2066,11 @@ static void scan_blocks()
dev->update_pos(dcr);
tot_files = dev->file;
for (;;) {
if (!dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
Dmsg1(100, "!read_block(): ERR=%s\n", dev->bstrerror());
if (dev->at_eot()) {
switch(dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
case Ok:
// no special handling required
break;
case EndOfTape:
if (blocks > 0) {
if (blocks==1) {
printf(_("1 block of %d bytes in file %d\n"), block_size, dev->file);
Expand All @@ -2079,8 +2081,7 @@ static void scan_blocks()
blocks = 0;
}
goto bail_out;
}
if (dev->at_eof()) {
case EndOfFile:
if (blocks > 0) {
if (blocks==1) {
printf(_("1 block of %d bytes in file %d\n"), block_size, dev->file);
Expand All @@ -2092,22 +2093,23 @@ static void scan_blocks()
}
printf(_("End of File mark.\n"));
continue;
}
if (bit_is_set(ST_SHORT, dev->state)) {
if (blocks > 0) {
if (blocks==1) {
printf(_("1 block of %d bytes in file %d\n"), block_size, dev->file);
default:
Dmsg1(100, "!read_block(): ERR=%s\n", dev->bstrerror());
if (bit_is_set(ST_SHORT, dev->state)) {
if (blocks > 0) {
if (blocks==1) {
printf(_("1 block of %d bytes in file %d\n"), block_size, dev->file);
}
else {
printf(_("%d blocks of %d bytes in file %d\n"), blocks, block_size, dev->file);
}
blocks = 0;
}
else {
printf(_("%d blocks of %d bytes in file %d\n"), blocks, block_size, dev->file);
}
blocks = 0;
printf(_("Short block read.\n"));
continue;
}
printf(_("Short block read.\n"));
continue;
}
printf(_("Error reading block. ERR=%s\n"), dev->bstrerror());
goto bail_out;
printf(_("Error reading block. ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
if (block->block_len != block_size) {
if (blocks > 0) {
Expand Down Expand Up @@ -2600,7 +2602,7 @@ static bool do_unfill()
goto bail_out;
}
Pmsg1(-1, _("Reading block %u.\n"), last_block_num);
if (!dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
if (Ok != dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
Pmsg1(-1, _("Error reading block: ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
Expand Down Expand Up @@ -2652,7 +2654,7 @@ static bool do_unfill()
goto bail_out;
}
Pmsg1(-1, _("Reading block %d.\n"), dev->block_num);
if (!dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
if (Ok != dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
Pmsg1(-1, _("Error reading block: ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
Expand All @@ -2668,7 +2670,7 @@ static bool do_unfill()
goto bail_out;
}
Pmsg1(-1, _("Reading block %d.\n"), dev->block_num);
if (!dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
if (Ok != dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
Pmsg1(-1, _("Error reading block: ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
Expand Down
14 changes: 12 additions & 2 deletions src/stored/dev.h
Expand Up @@ -74,6 +74,16 @@ enum {
W_WAKE
};

/**
* Return values for read_block_from_device()
*/
enum ReadStatus {
Error = 0,
Ok,
EndOfFile,
EndOfTape,
};

/**
* Arguments to open_dev()
*/
Expand Down Expand Up @@ -753,8 +763,8 @@ class SD_IMP_EXP DCR : public SMARTALLOC {
*/
bool write_block_to_device();
bool write_block_to_dev();
bool read_block_from_device(bool check_block_numbers);
bool read_block_from_dev(bool check_block_numbers);
ReadStatus read_block_from_device(bool check_block_numbers);
ReadStatus read_block_from_dev(bool check_block_numbers);

/*
* Methods in label.c
Expand Down
2 changes: 1 addition & 1 deletion src/stored/label.c
Expand Up @@ -140,7 +140,7 @@ int read_dev_volume_label(DCR *dcr)
empty_block(dcr->block);

Dmsg0(130, "Big if statement in read_volume_label\n");
if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
if (Ok != dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
Mmsg(jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bareos "
"labeled Volume, because: ERR=%s"), NPRT(VolName),
dev->print_name(), dev->print_errmsg());
Expand Down

0 comments on commit 2be266a

Please sign in to comment.