diff --git a/src/stored/backends/generic_tape_device.c b/src/stored/backends/generic_tape_device.c index eae18c0a037..d39d23b27aa 100644 --- a/src/stored/backends/generic_tape_device.c +++ b/src/stored/backends/generic_tape_device.c @@ -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()); diff --git a/src/stored/block.c b/src/stored/block.c index d6922d7467f..1aa2eabf4f0 100644 --- a/src/stored/block.c +++ b/src/stored/block.c @@ -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 { /* @@ -923,16 +923,16 @@ 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; } /** @@ -940,7 +940,7 @@ bool DCR::read_block_from_device(bool check_block_numbers) * 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; @@ -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", @@ -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: @@ -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; @@ -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, @@ -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; } /* @@ -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; @@ -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; } /* @@ -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"); @@ -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(); @@ -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; } diff --git a/src/stored/bls.c b/src/stored/bls.c index 0eee7726d43..4a63087ace8 100644 --- a/src/stored/bls.c +++ b/src/stored/bls.c @@ -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; @@ -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", diff --git a/src/stored/btape.c b/src/stored/btape.c index d8b68431112..a18454d338c 100644 --- a/src/stored/btape.c +++ b/src/stored/btape.c @@ -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; @@ -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")); @@ -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")); @@ -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); @@ -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); @@ -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) { @@ -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; } @@ -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; } @@ -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; } diff --git a/src/stored/dev.h b/src/stored/dev.h index 31760dcdc4e..112b8d35150 100644 --- a/src/stored/dev.h +++ b/src/stored/dev.h @@ -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() */ @@ -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 diff --git a/src/stored/label.c b/src/stored/label.c index 61fd2008c7f..721abaf2930 100644 --- a/src/stored/label.c +++ b/src/stored/label.c @@ -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()); diff --git a/src/stored/read_record.c b/src/stored/read_record.c index 54aba35847f..5241b22b4c6 100644 --- a/src/stored/read_record.c +++ b/src/stored/read_record.c @@ -178,7 +178,7 @@ void read_context_set_record(DCR *dcr, READ_CTX *rctx) * * Returns: true on success * false on error - * + e * Any fatal error sets the status bool to false. */ bool read_next_block_from_device(DCR *dcr, @@ -191,8 +191,11 @@ bool read_next_block_from_device(DCR *dcr, DEV_RECORD *trec; while (1) { - if (!dcr->read_block_from_device(CHECK_BLOCK_NUMBERS)) { - if (dcr->dev->at_eot()) { + switch(dcr->read_block_from_device(CHECK_BLOCK_NUMBERS)) { + case Ok: + // no handling required if read was successful + break; + case EndOfTape: Jmsg(jcr, M_INFO, 0, _("End of Volume at file %u on device %s, Volume \"%s\"\n"), dcr->dev->file, dcr->dev->print_name(), dcr->VolumeName); @@ -239,26 +242,27 @@ bool read_next_block_from_device(DCR *dcr, * After reading label, we must read first data block */ continue; - } else if (dcr->dev->at_eof()) { + case EndOfFile: Dmsg3(200, "End of file %u on device %s, Volume \"%s\"\n", dcr->dev->file, dcr->dev->print_name(), dcr->VolumeName); continue; - } else if (dcr->dev->is_short_block()) { - Jmsg1(jcr, M_ERROR, 0, "%s", dcr->dev->errmsg); - continue; - } else { - /* - * I/O error or strange end of tape - */ - display_tape_error_status(jcr, dcr->dev); - if (forge_on || jcr->ignore_label_errors) { - dcr->dev->fsr(1); /* try skipping bad record */ - Pmsg0(000, _("Did fsr in attemp to skip bad record.\n")); + default: + if (dcr->dev->is_short_block()) { + Jmsg1(jcr, M_ERROR, 0, "%s", dcr->dev->errmsg); continue; + } else { + /* + * I/O error or strange end of tape + */ + display_tape_error_status(jcr, dcr->dev); + if (forge_on || jcr->ignore_label_errors) { + dcr->dev->fsr(1); /* try skipping bad record */ + Pmsg0(000, _("Did fsr in attemp to skip bad record.\n")); + continue; + } + *status = false; + return false; } - *status = false; - return false; - } } Dmsg2(dbglvl, "Read new block at pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num); diff --git a/src/stored/stored_conf.c b/src/stored/stored_conf.c index c009987347e..980d360ee1a 100644 --- a/src/stored/stored_conf.c +++ b/src/stored/stored_conf.c @@ -205,6 +205,7 @@ static RES_ITEM dev_items[] = { { "AutoDeflateLevel", CFG_TYPE_PINT16, ITEM(res_dev.autodeflate_level), 0, CFG_ITEM_DEFAULT, "6", "13.4.0-", NULL }, { "AutoInflate", CFG_TYPE_IODIRECTION, ITEM(res_dev.autoinflate), 0, 0, NULL, "13.4.0-", NULL }, { "CollectStatistics", CFG_TYPE_BOOL, ITEM(res_dev.collectstats), 0, CFG_ITEM_DEFAULT, "true", NULL, NULL }, + { "EofOnErrorIsEot", CFG_TYPE_BOOL, ITEM(res_dev.eof_on_error_is_eot), 0, CFG_ITEM_DEFAULT, NULL, NULL, NULL }, { NULL, 0, { 0 }, 0, 0, NULL, NULL, NULL } }; diff --git a/src/stored/stored_conf.h b/src/stored/stored_conf.h index 298aaa84eed..b1a208ac8d2 100644 --- a/src/stored/stored_conf.h +++ b/src/stored/stored_conf.h @@ -138,6 +138,7 @@ class DEVRES : public BRSRES { bool drive_crypto_enabled; /**< Enable hardware crypto */ bool query_crypto_status; /**< Query device for crypto status */ bool collectstats; /**< Set if statistics should be collected */ + bool eof_on_error_is_eot; /**< Interpret EOF during read error as EOT */ drive_number_t drive; /**< Autochanger logical drive number */ drive_number_t drive_index; /**< Autochanger physical drive index */ char cap_bits[CAP_BYTES]; /**< Capabilities of this device */