X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Fblock.c;h=8e5725adeb14614090534fb71a64f0f706f12743;hb=137f3636336f7057cbf709341a773afaea5a2eeb;hp=5a3028403e38d761e5ee2e8feb7d31f26784e93a;hpb=0a9df1396b3b144f5593c39cc14534bcb7827fac;p=bacula%2Fbacula diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index 5a3028403e..8e5725adeb 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -38,7 +38,7 @@ extern int debug_level; * Dump the block header, then walk through * the block printing out the record headers. */ -void dump_block(DEV_BLOCK *b, char *msg) +void dump_block(DEV_BLOCK *b, const char *msg) { ser_declare; char *p; @@ -116,17 +116,28 @@ DEV_BLOCK *new_block(DEVICE *dev) block->dev = dev; block->block_len = block->buf_len; /* default block size */ block->buf = get_memory(block->buf_len); - if (block->buf == NULL) { - Mmsg0(&dev->errmsg, _("Unable to malloc block buffer.\n")); - Emsg0(M_FATAL, 0, dev->errmsg); - return NULL; - } empty_block(block); block->BlockVer = BLOCK_VER; /* default write version */ Dmsg1(90, "Returning new block=%x\n", block); return block; } + +/* + * Duplicate an existing block (eblock) + */ +DEV_BLOCK *dup_block(DEV_BLOCK *eblock) +{ + DEV_BLOCK *block = (DEV_BLOCK *)get_memory(sizeof(DEV_BLOCK)); + int buf_len = sizeof_pool_memory(eblock->buf); + + memcpy(block, eblock, sizeof(DEV_BLOCK)); + block->buf = get_memory(buf_len); + memcpy(block->buf, eblock->buf, buf_len); + return block; +} + + /* * Only the first block checksum error was reported. * If there are more, report it now. @@ -134,7 +145,7 @@ DEV_BLOCK *new_block(DEVICE *dev) void print_block_read_errors(JCR *jcr, DEV_BLOCK *block) { if (block->read_errors > 1) { - Jmsg(jcr, M_ERROR, 0, _("%d block read errors ignored.\n"), + Jmsg(jcr, M_ERROR, 0, _("%d block read errors not printed.\n"), block->read_errors); } } @@ -166,7 +177,7 @@ void empty_block(DEV_BLOCK *block) * in the buffer should have already been reserved by * init_block. */ -static void ser_block_header(DEV_BLOCK *block) +void ser_block_header(DEV_BLOCK *block) { ser_declare; uint32_t CheckSum = 0; @@ -195,10 +206,10 @@ static void ser_block_header(DEV_BLOCK *block) * Unserialize the block header for reading block. * This includes setting all the buffer pointers correctly. * - * Returns: 0 on failure (not a block) - * 1 on success + * Returns: false on failure (not a block) + * true on success */ -static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) +static bool unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) { ser_declare; char Id[BLKHDR_ID_LENGTH+1]; @@ -221,13 +232,14 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) block->BlockVer = 1; block->bufp = block->buf + bhl; if (strncmp(Id, BLKHDR1_ID, BLKHDR_ID_LENGTH) != 0) { - Mmsg2(&dev->errmsg, _("Buffer ID error. Wanted: %s, got %s. Buffer discarded.\n"), - BLKHDR1_ID, Id); + dev->dev_errno = EIO; + Mmsg4(&dev->errmsg, _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". Buffer discarded.\n"), + dev->file, dev->block_num, BLKHDR1_ID, Id); if (block->read_errors == 0 || verbose >= 2) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); } block->read_errors++; - return 0; + return false; } } else if (Id[3] == '2') { unser_uint32(block->VolSessionId); @@ -236,32 +248,38 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) block->BlockVer = 2; block->bufp = block->buf + bhl; if (strncmp(Id, BLKHDR2_ID, BLKHDR_ID_LENGTH) != 0) { - Mmsg2(&dev->errmsg, _("Buffer ID error. Wanted: %s, got %s. Buffer discarded.\n"), - BLKHDR2_ID, Id); + dev->dev_errno = EIO; + Mmsg4(&dev->errmsg, _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". Buffer discarded.\n"), + dev->file, dev->block_num, BLKHDR2_ID, Id); if (block->read_errors == 0 || verbose >= 2) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); } block->read_errors++; - return 0; + return false; } } else { - Mmsg1(&dev->errmsg, _("Expected block-id BB01 or BB02, got %s. Buffer discarded.\n"), Id); + dev->dev_errno = EIO; + Mmsg4(&dev->errmsg, _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". Buffer discarded.\n"), + dev->file, dev->block_num, BLKHDR2_ID, Id); if (block->read_errors == 0 || verbose >= 2) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); } block->read_errors++; - return 0; + unser_uint32(block->VolSessionId); + unser_uint32(block->VolSessionTime); + return false; } /* Sanity check */ if (block_len > MAX_BLOCK_LENGTH) { - Mmsg1(&dev->errmsg, _("Block length %u is insane (too large), probably due to a bad archive.\n"), - block_len); + dev->dev_errno = EIO; + Mmsg3(&dev->errmsg, _("Volume data error at %u:%u! Block length %u is insane (too large), probably due to a bad archive.\n"), + dev->file, dev->block_num, block_len); if (block->read_errors == 0 || verbose >= 2) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); } block->read_errors++; - return 0; + return false; } Dmsg1(190, "unser_block_header block_len=%d\n", block_len); @@ -280,91 +298,111 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) BlockCheckSum = bcrc32((uint8_t *)block->buf+BLKHDR_CS_LENGTH, block_len-BLKHDR_CS_LENGTH); if (BlockCheckSum != CheckSum) { - Mmsg3(&dev->errmsg, _("Block checksum mismatch in block %u: calc=%x blk=%x\n"), - (unsigned)BlockNumber, BlockCheckSum, CheckSum); + dev->dev_errno = EIO; + Mmsg5(&dev->errmsg, _("Volume data error at %u:%u! Block checksum mismatch in block %u: calc=%x blk=%x\n"), + dev->file, dev->block_num, (unsigned)BlockNumber, BlockCheckSum, CheckSum); if (block->read_errors == 0 || verbose >= 2) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); } block->read_errors++; - return 0; + if (!forge_on) { + return false; + } } } - return 1; + return true; } /* * Write a block to the device, with locking and unlocking * - * Returns: 1 on success - * : 0 on failure + * Returns: true on success + * : false on failure * */ -int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) +bool write_block_to_device(DCR *dcr, DEV_BLOCK *block) { - int stat = 1; - lock_device(dev); + bool stat = true; + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; + + if (dcr->spooling) { + stat = write_block_to_spool_file(dcr, block); + return stat; + } + + if (!dcr->dev_locked) { + lock_device(dev); + } /* * If a new volume has been mounted since our last write * Create a JobMedia record for the previous volume written, * and set new parameters to write this volume - * The saem applies for if we are in a new file. + * The same applies for if we are in a new file. */ - if (jcr->NewVol || jcr->NewFile) { + if (dcr->NewVol || dcr->NewFile) { /* Create a jobmedia record for this job */ - if (!dir_create_jobmedia_record(jcr)) { + if (!dir_create_jobmedia_record(dcr)) { + dev->dev_errno = EIO; Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"), jcr->VolCatInfo.VolCatName, jcr->Job); - set_new_volume_parameters(jcr, dev); - unlock_device(dev); - return 0; + set_new_volume_parameters(dcr); + stat = false; + goto bail_out; } - if (jcr->NewVol) { + if (dcr->NewVol) { /* Note, setting a new volume also handles any pending new file */ - set_new_volume_parameters(jcr, dev); - jcr->NewFile = false; /* this handled for new file too */ + set_new_volume_parameters(dcr); + dcr->NewFile = false; /* this handled for new file too */ } else { - set_new_file_parameters(jcr, dev); + set_new_file_parameters(dcr); } } - if (!write_block_to_dev(jcr, dev, block)) { - stat = fixup_device_block_write_error(jcr, dev, block); + if (!write_block_to_dev(dcr, block)) { + stat = fixup_device_block_write_error(dcr, block); } - unlock_device(dev); +bail_out: + if (!dcr->dev_locked) { + unlock_device(dev); + } return stat; } /* * Write a block to the device * - * Returns: 1 on success or EOT - * 0 on hard error + * Returns: true on success or EOT + * false on hard error */ -int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) +bool write_block_to_dev(DCR *dcr, DEV_BLOCK *block) { ssize_t stat = 0; uint32_t wlen; /* length to write */ int hit_max1, hit_max2; bool ok; + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; #ifdef NO_TAPE_WRITE_TEST empty_block(block); - return 1; + return true; #endif ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf))); /* dump_block(block, "before write"); */ if (dev->state & ST_WEOT) { Dmsg0(100, "return write_block_to_dev with ST_WEOT\n"); + dev->dev_errno = ENOSPC; Jmsg(jcr, M_FATAL, 0, _("Cannot write block. Device at EOM.\n")); - return 0; + return false; } wlen = block->binbuf; if (wlen <= WRITE_BLKHDR_LENGTH) { /* Does block have data in it? */ Dmsg0(100, "return write_block_to_dev no data to write\n"); - return 1; + return true; } /* * Clear to the end of the buffer if it is not full, @@ -378,12 +416,15 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) /* Adjust write size to min/max for tapes only */ if (dev->state & ST_TAPE) { - if (wlen < dev->min_block_size) { - wlen = ((dev->min_block_size + TAPE_BSIZE - 1) / TAPE_BSIZE) * TAPE_BSIZE; - } /* check for fixed block size */ if (dev->min_block_size == dev->max_block_size) { wlen = block->buf_len; /* fixed block size already rounded */ + /* Check for min block size */ + } else if (wlen < dev->min_block_size) { + wlen = ((dev->min_block_size + TAPE_BSIZE - 1) / TAPE_BSIZE) * TAPE_BSIZE; + /* Ensure size is rounded */ + } else { + wlen = ((wlen + TAPE_BSIZE - 1) / TAPE_BSIZE) * TAPE_BSIZE; } } if (wlen-blen > 0) { @@ -408,7 +449,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) max_cap = dev->VolCatInfo.VolCatMaxBytes; } Jmsg(jcr, M_INFO, 0, _("User defined maximum volume capacity %s exceeded on device %s.\n"), - edit_uint64(max_cap, ed1), dev->dev_name); + edit_uint64_with_commas(max_cap, ed1), dev->dev_name); block->write_failed = true; if (weof_dev(dev, 1) != 0) { /* end tape */ Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); @@ -417,58 +458,90 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) /* Don't do update after second EOF or file count will be wrong */ Dmsg0(100, "dir_update_volume_info\n"); dev->VolCatInfo.VolCatFiles = dev->file; - dir_update_volume_info(jcr, dev, 0); + dir_update_volume_info(dcr, false); if (dev_cap(dev, CAP_TWOEOF) && weof_dev(dev, 1) != 0) { /* write eof */ Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); dev->VolCatInfo.VolCatErrors++; } dev->state |= (ST_EOF | ST_EOT | ST_WEOT); - return 0; + dev->dev_errno = ENOSPC; + return false; } /* Limit maximum File size on volume to user specified value */ - if (dev_state(dev, ST_TAPE)) { - if ((dev->max_file_size > 0) && - (dev->file_addr+block->binbuf) >= dev->max_file_size) { + if ((dev->max_file_size > 0) && + (dev->file_size+block->binbuf) >= dev->max_file_size) { + if (dev_state(dev, ST_TAPE) && weof_dev(dev, 1) != 0) { /* write eof */ /* Write EOF */ - if (weof_dev(dev, 1) != 0) { /* write eof */ - Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); - block->write_failed = true; - dev->VolCatInfo.VolCatErrors++; - dev->state |= (ST_EOF | ST_EOT | ST_WEOT); - Dmsg0(100, "dir_update_volume_info\n"); - dev->VolCatInfo.VolCatFiles = dev->file; - dir_update_volume_info(jcr, dev, 0); - return 0; - } - - /* Do bookkeeping to handle EOF just written */ + Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); + block->write_failed = true; + dev->VolCatInfo.VolCatErrors++; + dev->state |= (ST_EOF | ST_EOT | ST_WEOT); Dmsg0(100, "dir_update_volume_info\n"); dev->VolCatInfo.VolCatFiles = dev->file; - dir_update_volume_info(jcr, dev, 0); - if (!dir_create_jobmedia_record(jcr)) { - Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"), - jcr->VolCatInfo.VolCatName, jcr->Job); - return 0; + dir_update_volume_info(dcr, false); + dev->dev_errno = ENOSPC; + return false; + } + + /* Create a JobMedia record so restore can seek */ + Dmsg0(100, "dir_update_volume_info\n"); + dev->VolCatInfo.VolCatFiles = dev->file; + dir_update_volume_info(dcr, false); + if (!dir_create_jobmedia_record(dcr)) { + dev->dev_errno = EIO; + Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"), + dcr->VolCatInfo.VolCatName, jcr->Job); + if (!forge_on) { + return false; + } + } + dev->file_size = 0; /* reset file size */ + /* + * Walk through all attached jcrs indicating the file has changed + */ + Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName); +#ifdef xxx + for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) { + if (mjcr->JobId == 0) { + continue; /* ignore console */ } - /* - * Walk through all attached jcrs indicating the file has changed - */ - Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName); - for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) { - if (mjcr->JobId == 0) { - continue; /* ignore console */ - } - mjcr->NewFile = true; /* set reminder to do set_new_file_params */ + mjcr->dcr->NewFile = true; /* set reminder to do set_new_file_params */ + } +#endif + /* + * Walk through all attached dcrs setting flag to call + * set_new_file_parameters() when that dcr is next used. + */ + DCR *mdcr; + foreach_dlist(mdcr, dev->attached_dcrs) { + if (mdcr->jcr->JobId == 0) { + continue; } - set_new_file_parameters(jcr, dev); + mdcr->NewFile = true; /* set reminder to do set_new_file_params */ } + /* Set new file/block parameters for current dcr */ + set_new_file_parameters(dcr); } dev->VolCatInfo.VolCatWrites++; - Dmsg1(300, "Write block of %u bytes\n", wlen); + Dmsg1(200, "Write block of %u bytes\n", wlen); +#ifdef DEBUG_BLOCK_ZEROING + uint32_t *bp = (uint32_t *)block->buf; + if (bp[0] == 0 && bp[1] == 0 && bp[2] == 0 && block->buf[12] == 0) { + Jmsg0(jcr, M_ABORT, 0, "Write block header zeroed.\n"); + } +#endif + stat = write(dev->fd, block->buf, (size_t)wlen); + +#ifdef DEBUG_BLOCK_ZEROING + if (bp[0] == 0 && bp[1] == 0 && bp[2] == 0 && block->buf[12] == 0) { + Jmsg0(jcr, M_ABORT, 0, "Write block header zeroed.\n"); + } +#endif + if (stat != (ssize_t)wlen) { /* We should check for errno == ENOSPC, BUT many * devices simply report EIO when the volume is full. @@ -489,11 +562,12 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (dev->dev_errno == 0) { dev->dev_errno = ENOSPC; /* out of space */ } - Jmsg(jcr, M_ERROR, 0, _("Write error at %u:%u on device %s. ERR=%s.\n"), + Jmsg4(jcr, M_ERROR, 0, _("Write error at %u:%u on device %s. ERR=%s.\n"), dev->file, dev->block_num, dev->dev_name, strerror(dev->dev_errno)); } else { dev->dev_errno = ENOSPC; /* out of space */ - Jmsg(jcr, M_INFO, 0, _("End of medium at %u:%u on device %s. Write of %u bytes got %d.\n"), + Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s. Write of %u bytes got %d.\n"), + dev->VolCatInfo.VolCatName, dev->file, dev->block_num, dev->dev_name, wlen, stat); } @@ -507,7 +581,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) } Dmsg0(100, "dir_update_volume_info\n"); dev->VolCatInfo.VolCatFiles = dev->file; - dir_update_volume_info(jcr, dev, 0); + dir_update_volume_info(dcr, false); if (dev_cap(dev, CAP_TWOEOF) && weof_dev(dev, 1) != 0) { /* end the tape */ dev->VolCatInfo.VolCatErrors++; Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); @@ -524,7 +598,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) * then re-read it and verify that the block number is * correct. */ - if (dev->state & ST_TAPE && dev_cap(dev, CAP_BSR)) { + if ((dev->state & ST_TAPE) && dev_cap(dev, CAP_BSR)) { /* Now back up over what we wrote and read the last block */ if (!bsf_dev(dev, 1)) { @@ -552,7 +626,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (ok) { DEV_BLOCK *lblock = new_block(dev); /* Note, this can destroy dev->errmsg */ - if (!read_block_from_dev(jcr, dev, lblock, NO_BLOCK_NUMBER_CHECK)) { + if (!read_block_from_dev(dcr, lblock, NO_BLOCK_NUMBER_CHECK)) { Jmsg(jcr, M_ERROR, 0, _("Re-read last block at EOT failed. ERR=%s"), dev->errmsg); } else { if (lblock->BlockNumber+1 == block->BlockNumber) { @@ -567,14 +641,13 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) } } #endif - return 0; + return false; } /* We successfully wrote the block, now do housekeeping */ dev->VolCatInfo.VolCatBytes += block->binbuf; dev->VolCatInfo.VolCatBlocks++; - dev->file_addr += wlen; dev->EndBlock = dev->block_num; dev->EndFile = dev->file; dev->block_num++; @@ -582,36 +655,40 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) /* Update jcr values */ if (dev_state(dev, ST_TAPE)) { - jcr->EndBlock = dev->EndBlock; - jcr->EndFile = dev->EndFile; + dcr->EndBlock = dev->EndBlock; + dcr->EndFile = dev->EndFile; } else { - jcr->EndBlock = (uint32_t)dev->file_addr; - jcr->EndFile = (uint32_t)(dev->file_addr >> 32); + /* Save address of start of block just written */ + dcr->EndBlock = (uint32_t)dev->file_addr; + dcr->EndFile = (uint32_t)(dev->file_addr >> 32); } - if (jcr->VolFirstIndex == 0 && block->FirstIndex > 0) { - jcr->VolFirstIndex = block->FirstIndex; + if (dcr->VolFirstIndex == 0 && block->FirstIndex > 0) { + dcr->VolFirstIndex = block->FirstIndex; } if (block->LastIndex > 0) { - jcr->VolLastIndex = block->LastIndex; + dcr->VolLastIndex = block->LastIndex; } - jcr->WroteVol = true; + dcr->WroteVol = true; + dev->file_addr += wlen; /* update file address */ + dev->file_size += wlen; Dmsg2(190, "write_block: wrote block %d bytes=%d\n", dev->block_num, wlen); empty_block(block); - return 1; + return true; } /* * Read block with locking * */ -int read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers) +bool read_block_from_device(DCR *dcr, DEV_BLOCK *block, bool check_block_numbers) { - int stat; + bool stat; + DEVICE *dev = dcr->dev; Dmsg0(90, "Enter read_block_from_device\n"); lock_device(dev); - stat = read_block_from_dev(jcr, dev, block, check_block_numbers); + stat = read_block_from_dev(dcr, block, check_block_numbers); unlock_device(dev); Dmsg0(90, "Leave read_block_from_device\n"); return stat; @@ -622,51 +699,61 @@ int read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_b * the block header. For a file, the block may be partially * or completely in the current buffer. */ -int read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers) +bool read_block_from_dev(DCR *dcr, DEV_BLOCK *block, bool check_block_numbers) { ssize_t stat; int looping; uint32_t BlockNumber; int retry; + JCR *jcr = dcr->jcr; + DEVICE *dev = dcr->dev; if (dev_state(dev, ST_EOT)) { - return 0; + return false; } looping = 0; Dmsg1(100, "Full read() in read_block_from_device() len=%d\n", block->buf_len); reread: if (looping > 1) { + dev->dev_errno = EIO; Mmsg1(&dev->errmsg, _("Block buffer size looping problem on device %s\n"), dev->dev_name); Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); block->read_len = 0; - return 0; + return false; } retry = 0; do { +// uint32_t *bp = (uint32_t *)block->buf; +// Dmsg3(000, "Read %p %u at %llu\n", block->buf, block->buf_len, lseek(dev->fd, 0, SEEK_CUR)); + stat = read(dev->fd, block->buf, (size_t)block->buf_len); + +// Dmsg8(000, "stat=%d Csum=%u blen=%u bnum=%u %c%c%c%c\n",stat, bp[0],bp[1],bp[2], +// block->buf[12],block->buf[13],block->buf[14],block->buf[15]); + if (retry == 1) { dev->VolCatInfo.VolCatErrors++; } } while (stat == -1 && (errno == EINTR || errno == EIO) && retry++ < 11); -// Dmsg1(100, "read stat = %d\n", stat); if (stat < 0) { Dmsg1(90, "Read device got: ERR=%s\n", strerror(errno)); clrerror_dev(dev, -1); block->read_len = 0; - Mmsg2(&dev->errmsg, _("Read error on device %s. ERR=%s.\n"), - dev->dev_name, strerror(dev->dev_errno)); + Mmsg4(&dev->errmsg, _("Read error at file:blk %u:%u on device %s. ERR=%s.\n"), + dev->file, dev->block_num, dev->dev_name, strerror(dev->dev_errno)); Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); if (dev->state & ST_EOF) { /* EOF just seen? */ dev->state |= ST_EOT; /* yes, error => EOT */ } - return 0; + return false; } Dmsg1(90, "Read device got %d bytes\n", stat); if (stat == 0) { /* Got EOF ! */ dev->block_num = block->read_len = 0; - Mmsg1(&dev->errmsg, _("Read zero bytes on device %s.\n"), dev->dev_name); + Mmsg3(&dev->errmsg, _("Read zero bytes at %u:%u on device %s.\n"), + dev->file, dev->block_num, dev->dev_name); if (dev->state & ST_EOF) { /* EOF already read? */ dev->state |= ST_EOT; /* yes, 2 EOFs => EOT */ block->read_len = 0; @@ -675,23 +762,28 @@ reread: dev->file++; /* increment file */ dev->state |= ST_EOF; /* set EOF read */ block->read_len = 0; - return 0; /* return eof */ + return false; /* return eof */ } /* Continue here for successful read */ block->read_len = stat; /* save length read */ if (block->read_len < BLKHDR2_LENGTH) { - Mmsg2(&dev->errmsg, _("Very short block of %d bytes on device %s discarded.\n"), - block->read_len, dev->dev_name); + dev->dev_errno = EIO; + Mmsg4(&dev->errmsg, _("Volume data error at %u:%u! Very short block of %d bytes on device %s discarded.\n"), + dev->file, dev->block_num, block->read_len, dev->dev_name); Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); dev->state |= ST_SHORT; /* set short block */ block->read_len = block->binbuf = 0; - return 0; /* return error */ + return false; /* return error */ } BlockNumber = block->BlockNumber + 1; if (!unser_block_header(jcr, dev, block)) { - block->read_len = 0; - return 0; + if (forge_on) { + dev->file_addr += block->read_len; + dev->file_size += block->read_len; + goto reread; + } + return false; } /* @@ -700,6 +792,7 @@ reread: * and go re-read. */ if (block->block_len > block->buf_len) { + dev->dev_errno = EIO; Mmsg2(&dev->errmsg, _("Block length %u is greater than buffer %u. Attempting recovery.\n"), block->block_len, block->buf_len); Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); @@ -710,13 +803,14 @@ reread: if (!bsr_dev(dev, 1)) { Jmsg(jcr, M_ERROR, 0, "%s", strerror_dev(dev)); block->read_len = 0; - return 0; + return false; } } else { - Dmsg0(100, "Seek to beginning of block for reread.\n"); + Dmsg0(200, "Seek to beginning of block for reread.\n"); off_t pos = lseek(dev->fd, (off_t)0, SEEK_CUR); /* get curr pos */ pos -= block->read_len; lseek(dev->fd, pos, SEEK_SET); + dev->file_addr = pos; } Mmsg1(&dev->errmsg, _("Setting block buffer size to %u bytes.\n"), block->block_len); Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg); @@ -732,12 +826,13 @@ reread: } if (block->block_len > block->read_len) { - Mmsg3(&dev->errmsg, _("Short block at %u of %d bytes on device %s discarded.\n"), - dev->block_num, block->read_len, dev->dev_name); + dev->dev_errno = EIO; + Mmsg4(&dev->errmsg, _("Volume data error at %u:%u! Short block of %d bytes on device %s discarded.\n"), + dev->file, dev->block_num, block->read_len, dev->dev_name); Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); dev->state |= ST_SHORT; /* set short block */ block->read_len = block->binbuf = 0; - return 0; /* return error */ + return false; /* return error */ } dev->state &= ~(ST_EOF|ST_SHORT); /* clear EOF and short block */ @@ -746,19 +841,22 @@ reread: dev->VolCatInfo.VolCatBytes += block->block_len; dev->VolCatInfo.VolCatBlocks++; - dev->file_addr += block->block_len; dev->EndBlock = dev->block_num; dev->EndFile = dev->file; dev->block_num++; /* Update jcr values */ if (dev->state & ST_TAPE) { - jcr->EndBlock = dev->EndBlock; - jcr->EndFile = dev->EndFile; + dcr->EndBlock = dev->EndBlock; + dcr->EndFile = dev->EndFile; } else { - jcr->EndBlock = (uint32_t)dev->file_addr; - jcr->EndFile = (uint32_t)(dev->file_addr >> 32); + dcr->EndBlock = (uint32_t)dev->file_addr; + dcr->EndFile = (uint32_t)(dev->file_addr >> 32); + dev->block_num = dcr->EndBlock; + dev->file = dcr->EndFile; } + dev->file_addr += block->block_len; + dev->file_size += block->block_len; /* * If we read a short block on disk, @@ -778,11 +876,13 @@ reread: off_t pos = lseek(dev->fd, (off_t)0, SEEK_CUR); /* get curr pos */ pos -= (block->read_len - block->block_len); lseek(dev->fd, pos, SEEK_SET); - Dmsg2(100, "Did lseek blk_size=%d rdlen=%d\n", block->block_len, + Dmsg2(200, "Did lseek blk_size=%d rdlen=%d\n", block->block_len, block->read_len); + dev->file_addr = pos; + dev->file_size = pos; } Dmsg2(200, "Exit read_block read_len=%d block_len=%d\n", block->read_len, block->block_len); block->block_read = true; - return 1; + return true; }