From 65fbbb5584c165660df8a4ade33abac52c95d842 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Fri, 13 Dec 2002 14:23:29 +0000 Subject: [PATCH] btape + doc updates for fixed block devices git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@239 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 17 +-- bacula/src/stored/btape.c | 230 +++++++++++++++++++++++++++++--------- 2 files changed, 188 insertions(+), 59 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index 8747fd4b3b..c92cd8e1f5 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 11 December 2002 + 12 December 2002 Documentation to do: (a little bit at a time) - Document running a test version. @@ -12,22 +12,22 @@ Testing to do: (painful) - blocksize recognition code. - Test new BSR code (mostly done). - Test watchdog child timer code. +- Test that EndFile/Block are correctly updated at end of tape + (in view of new block reading code). For 1.28 release: +- Count number of ignored messages in bscan and print when first + SOS is found. - Need a verbose mode in restore, perhaps to bsr. - Should we dump a SOS when starting a new tape? - bscan without -v is too quiet -- perhaps show jobs. -- Get rid of bscan.c:534 error message (one time only). -- Print some statistics when get EOF on device in bscan -- feedback - to let user know it is working. - Add code to reject whole blocks if not wanted on restore. - Figure out how to allow multiple simultaneous file Volumes on a single device. - Start working on Base jobs. - Implement FileOptions (see end of this document) -- Ensure that restore of differential jobs works (check SQL). - Make sure the MaxVolFiles is fully implemented in SD - Flush all the daemon messages at the end of every job. - Check if both CatalogFiles and UseCatalog are set to SD. @@ -77,7 +77,6 @@ For 1.28 release: allow -with-termcap-dir. - Enhance time and size scanning routines. - Fix Autoprune for Volumes to respect need for full save. -- DateWritten field on tape may be wrong. - Fix Win32 config file definition name on /install - No READLINE_SRC if found in alternate directory. - Add Client FS/OS id (Linux, Win95/98, ...). @@ -131,7 +130,6 @@ For 1.28 release: a single Storage specification) in the Job record. Thus a job can be backed up to a number of storage devices. - Implement dump label to UA -- Copy volume using single drive. - Concept of VolumeSet during restore which is a list of Volume names needed. - Restore files modified after date @@ -625,4 +623,9 @@ Done: (see kernsdone for more) - Volumes can be listed multiple times in Restore volume list. - Add watchdog timeout for child processes start_child_timer() end_child_timer(); +- Get rid of bscan.c:534 error message (one time only). +- Print some statistics when get EOF on device in bscan -- feedback + to let user know it is working. +- DateWritten field on tape may be wrong. +- Ensure that restore of differential jobs works (check SQL). diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index bd40505086..d074ccd849 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -63,6 +63,7 @@ static void unfillcmd(); static int flush_block(DEV_BLOCK *block, int dump); static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec); static int my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); +static void scan_blocks(); /* Static variables */ @@ -533,19 +534,21 @@ plus the header exceeds the block size (by default about 64K\n"); sm_check(__FILE__, __LINE__, False); } -/* - * This is a general test of Bacula's functions - * needed to read and write the tape. - */ -static void testcmd() +static int re_read_block_test() { DEV_BLOCK *block; DEV_RECORD *rec; + int stat = 0; int len; - Pmsg0(0, "\nWrite, backup, and re-read test.\n\n" -"I'm going to write three records and two eof's\n" -"then backup over the eof's and re-read the last record.\n\n"); + if (!(dev->capabilities & CAP_EOM)) { + Pmsg0(-1, _("Skipping read backwards test because MT_EOM turned off.\n")); + return 0; + } + + Pmsg0(-1, _("\nWrite, backup, and re-read test.\n\n" + "I'm going to write three records and two eof's\n" + "then backup over the eof's and re-read the last record.\n\n")); rewindcmd(); block = new_block(dev); rec = new_record(); @@ -553,75 +556,86 @@ static void testcmd() len = rec->data_len = block->buf_len-100; memset(rec->data, 1, rec->data_len); if (!write_record_to_block(block, rec)) { - Pmsg0(0, "Error writing record to block.\n"); + Pmsg0(0, _("Error writing record to block.\n")); goto bail_out; } if (!write_block_to_dev(jcr, dev, block)) { - Pmsg0(0, "Error writing block to device.\n"); + Pmsg0(0, _("Error writing block to device.\n")); goto bail_out; } else { - Pmsg1(0, "Wrote one record of %d bytes.\n", rec->data_len); + Pmsg1(0, _("Wrote first record of %d bytes.\n"), rec->data_len); } memset(rec->data, 2, rec->data_len); if (!write_record_to_block(block, rec)) { - Pmsg0(0, "Error writing record to block.\n"); + Pmsg0(0, _("Error writing record to block.\n")); goto bail_out; } if (!write_block_to_dev(jcr, dev, block)) { - Pmsg0(0, "Error writing block to device.\n"); + Pmsg0(0, _("Error writing block to device.\n")); goto bail_out; } else { - Pmsg1(0, "Wrote one record of %d bytes.\n", rec->data_len); + Pmsg1(0, _("Wrote second record of %d bytes.\n"), rec->data_len); } memset(rec->data, 3, rec->data_len); if (!write_record_to_block(block, rec)) { - Pmsg0(0, "Error writing record to block.\n"); + Pmsg0(0, _("Error writing record to block.\n")); goto bail_out; } if (!write_block_to_dev(jcr, dev, block)) { - Pmsg0(0, "Error writing block to device.\n"); + Pmsg0(0, _("Error writing block to device.\n")); goto bail_out; } else { - Pmsg1(0, "Wrote one record of %d bytes.\n", rec->data_len); + Pmsg1(0, _("Wrote fourth record of %d bytes.\n"), rec->data_len); } weofcmd(); weofcmd(); if (bsf_dev(dev, 1) != 0) { - Pmsg1(0, "Back space file failed! ERR=%s\n", strerror(dev->dev_errno)); + Pmsg1(0, _("Back space file failed! ERR=%s\n"), strerror(dev->dev_errno)); goto bail_out; } if (bsf_dev(dev, 1) != 0) { - Pmsg1(0, "Back space file failed! ERR=%s\n", strerror(dev->dev_errno)); + Pmsg1(0, _("Back space file failed! ERR=%s\n"), strerror(dev->dev_errno)); goto bail_out; } Pmsg0(0, "Backspaced over two EOFs OK.\n"); if (bsr_dev(dev, 1) != 0) { - Pmsg1(0, "Back space record failed! ERR=%s\n", strerror(dev->dev_errno)); + Pmsg1(0, _("Back space record failed! ERR=%s\n"), strerror(dev->dev_errno)); goto bail_out; } Pmsg0(0, "Backspace record OK.\n"); if (!read_block_from_dev(dev, block)) { - Pmsg1(0, "Read block failed! ERR=%s\n", strerror(dev->dev_errno)); + Pmsg1(0, _("Read block failed! ERR=%s\n"), strerror(dev->dev_errno)); goto bail_out; } memset(rec->data, 0, rec->data_len); if (!read_record_from_block(block, rec)) { - Pmsg1(0, "Read block failed! ERR=%s\n", strerror(dev->dev_errno)); + Pmsg1(0, _("Read block failed! ERR=%s\n"), strerror(dev->dev_errno)); goto bail_out; } for (int i=0; idata[i] != 3) { - Pmsg0(0, "Bad data in record. Test failed!\n"); + Pmsg0(0, _("Bad data in record. Test failed!\n")); + Pmsg0(0, _("You might try adding:\n\n" + "Hardware End of File = No\n\n" + "to your Storage daemon's Device resource definition.\n")); goto bail_out; } } - Pmsg0(0, "Test succeeded!\n\n"); + Pmsg0(0, _("Re-read test succeeded!\n\n")); + stat = 1; +bail_out: + free_block(block); + free_record(rec); + return stat; +} - Pmsg0(0, "\nAppend files test.\n\n" +static int append_test() +{ + Pmsg0(-1, _("\n\n=== Append files test. ===\n\n" "I'm going to write one record in file 0,\n" " two records in file 1,\n" -" and three records in file 2\n\n"); +" and three records in file 2\n\n")); rewindcmd(); wrcmd(); weofcmd(); /* end file 0 */ @@ -632,51 +646,73 @@ static void testcmd() wrcmd(); wrcmd(); weofcmd(); /* end file 2 */ -// weofcmd(); rewindcmd(); - Pmsg0(0, "Now moving to end of media.\n"); + Pmsg0(0, _("Now moving to end of media.\n")); eodcmd(); - Pmsg2(0, "End Append files test.\n\ -We should be in file 3. I am at file %d. This is %s\n\n", + Pmsg2(-1, _("End Append files test.\n\ +We should be in file 3. I am at file %d. This is %s\n\n"), dev->file, dev->file == 3 ? "correct!" : "NOT correct!!!!"); - Pmsg0(0, "\nNow I am going to attempt to append to the tape.\n"); + if (dev->file != 3) { + Pmsg0(-1, _("To correct this problem, you might try adding:\n\n" + "Hardware End of Medium = No\n\n" + "to your Storage daemon's Device resource definition.\n")); + return 0; + } + + Pmsg0(-1, _("\nNow I am going to attempt to append to the tape.\n")); wrcmd(); weofcmd(); -// weofcmd(); rewindcmd(); - Pmsg0(0, "Done writing, scanning results ...\n\n"); - scancmd(); - Pmsg0(0, "End Append to the tape test.\n\ + Pmsg0(0, _("Done writing, scanning results ...\n\n")); + scan_blocks(); + Pmsg0(-1, _("End Append to the tape test.\n\ The above scan should have four files of:\n\ One record, two records, three records, and one record \n\ -respectively each with 64,512 bytes.\n\n"); +respectively each with 64,448 bytes.\n\n")); + Pmsg0(-1, _("If the above is not correct, you might try running Bacula\n" + "in fixed block mode by setting:\n\n" + "Minimum Block Size = nnn\n" + "Maximum Block Size = nnn\n\n" + "in your Storage daemon's Device definition.\n" + "nnn must match your tape driver's block size.\n")); + + return 1; +} + +/* + * This is a general test of Bacula's functions + * needed to read and write the tape. + */ +static void testcmd() +{ + re_read_block_test(); - Pmsg0(0, "Append block test.\n\ + if (!append_test()) { + return; + } + + Pmsg0(-1, "\n\n=== Append block test. ===\n\n\ I'm going to write a block, an EOF, rewind, go to EOM,\n\ then backspace over the EOF and attempt to append a second\n\ block in the first file.\n\n"); rewindcmd(); wrcmd(); weofcmd(); -// weofcmd(); rewindcmd(); eodcmd(); - Pmsg2(0, "We should be at file 1. I am at EOM File=%d. This is %s\n", + Pmsg2(-1, _("We should be at file 1. I am at EOM File=%d. This is %s\n"), dev->file, dev->file == 1 ? "correct!" : "NOT correct!!!!"); Pmsg0(0, "Doing backspace file.\n"); bsfcmd(); - Pmsg0(0, "Write second block, hoping to append to first file.\n"); + Pmsg0(0, _("Write second block, hoping to append to first file.\n")); wrcmd(); weofcmd(); rewindcmd(); - Pmsg0(0, "Done writing, scanning results ...\n\n"); - scancmd(); - Pmsg0(0, "The above should have one file of two blocks 64,512 bytes each.\n"); -bail_out: - free_record(rec); - free_block(block); + Pmsg0(0, _("Done writing, scanning results ...\n\n")); + scan_blocks(); + Pmsg0(-1, _("\nThe above should have one file of two blocks 64,448 bytes each.\n")); } @@ -718,6 +754,9 @@ static void rdcmd() } +/* + * Write a Bacula block to the tape + */ static void wrcmd() { DEV_BLOCK *block; @@ -736,17 +775,16 @@ static void wrcmd() rec->data_len = i; sm_check(__FILE__, __LINE__, False); if (!write_record_to_block(block, rec)) { - Pmsg0(0, "Error writing record to block.\n"); + Pmsg0(0, _("Error writing record to block.\n")); goto bail_out; } if (!write_block_to_dev(jcr, dev, block)) { - Pmsg0(0, "Error writing block to device.\n"); + Pmsg0(0, _("Error writing block to device.\n")); goto bail_out; } else { - Pmsg1(0, "Wrote one record of %d bytes.\n", - ((i+TAPE_BSIZE-1)/TAPE_BSIZE) * TAPE_BSIZE); + Pmsg1(0, _("Wrote one record of %d bytes.\n"), i); } - Pmsg0(0, "Wrote block to device.\n"); + Pmsg0(0, _("Wrote block to device.\n")); bail_out: sm_check(__FILE__, __LINE__, False); @@ -758,7 +796,8 @@ bail_out: /* * Scan tape by reading block by block. Report what is - * on the tape. + * on the tape. Note, this command does raw reads, and as such + * will not work with fixed block size devices. */ static void scancmd() { @@ -824,6 +863,93 @@ static void scancmd() printf("Total files=%d, blocks=%d, bytes = %" lld "\n", tot_files, tot_blocks, bytes); } + +/* + * Scan tape by reading Bacula block by block. Report what is + * on the tape. This function reads Bacula blocks, so if your + * Device resource is correctly defined, it should work with + * either variable or fixed block sizes. + */ +static void scan_blocks() +{ + int blocks, tot_blocks, tot_files; + uint32_t block_size; + uint64_t bytes; + DEV_BLOCK *block; + + block = new_block(dev); + blocks = block_size = tot_blocks = 0; + bytes = 0; + + update_pos_dev(dev); + tot_files = dev->file; + for (;;) { + if (!read_block_from_device(dev, block)) { + Dmsg1(100, "!read_block(): ERR=%s\n", strerror_dev(dev)); + if (dev->state & ST_EOT) { + if (blocks > 0) { + printf("%d block%s of %d bytes in file %d\n", + blocks, blocks>1?"s":"", block_size, dev->file); + blocks = 0; + } + goto bail_out; + } + if (dev->state & ST_EOF) { + if (blocks > 0) { + printf("%d block%s of %d bytes in file %d\n", + blocks, blocks>1?"s":"", block_size, dev->file); + blocks = 0; + } + printf(_("End of File mark.\n")); + continue; + } + if (dev->state & ST_SHORT) { + if (blocks > 0) { + printf("%d block%s of %d bytes in file %d\n", + blocks, blocks>1?"s":"", block_size, dev->file); + blocks = 0; + } + printf(_("Short block read.\n")); + continue; + } + printf(_("Error reading block. ERR=%s\n"), strerror_dev(dev)); + goto bail_out; + } + if (block->block_len != block_size) { + if (blocks > 0) { + printf("%d block%s of %d bytes in file %d\n", + blocks, blocks>1?"s":"", block_size, dev->file); + blocks = 0; + } + block_size = block->block_len; + } + blocks++; + tot_blocks++; + bytes += block->block_len; + Dmsg5(100, "Blk=%u blen=%u bVer=%d SessId=%u SessTim=%u\n", + block->BlockNumber, block->block_len, block->BlockVer, + block->VolSessionId, block->VolSessionTime); + if (verbose == 1) { + DEV_RECORD *rec = new_record(); + read_record_from_block(block, rec); + Pmsg7(-1, "Block: %u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n", + block->BlockNumber, block->block_len, + FI_to_ascii(rec->FileIndex), rec->VolSessionId, rec->VolSessionTime, + stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len); + rec->remainder = 0; + free_record(rec); + } else if (verbose > 1) { + dump_block(block, ""); + } + + } +bail_out: + free_block(block); + tot_files = dev->file - tot_files; + printf("Total files=%d, blocks=%d, bytes = %" lld "\n", tot_files, tot_blocks, bytes); +} + + static void statcmd() { int stat = 0; -- 2.39.5