static void rewindcmd();
static void clearcmd();
static void wrcmd();
+static void rrcmd();
static void eodcmd();
static void fillcmd();
+static void statcmd();
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 time_t now;
static double kbs;
static long file_index;
-static int verbose = 0;
static int end_of_tape = 0;
static uint32_t LastBlock = 0;
static uint32_t eot_block;
printf("%sSHORT ", dev->state & ST_SHORT ? "" : "!");
printf("\n");
+ printf(_("Device parameters:\n"));
+ printf("Device name: %s\n", dev->dev_name);
+ printf("File=%u block=%u\n", dev->file, dev->block_num);
+ printf("Min block=%u Max block=%u\n", dev->min_block_size, dev->max_block_size);
+
+ printf("Status:\n");
+ statcmd();
+
}
/*
DEV_RECORD *rec;
int i, blkno = 0;
- Pmsg0(0, "Test writting larger and larger records.\n\
-This is a torture test for records.\nI am going to write\n\
-larger and larger records. It will stop when the record size\n\
-plus the header exceeds the block size (by default about 64K\n");
+ Pmsg0(0, "Test writting larger and larger records.\n"
+"This is a torture test for records.\nI am going to write\n"
+"larger and larger records. It will stop when the record size\n"
+"plus the header exceeds the block size (by default about 64K)\n");
get_cmd("Do you want to continue? (y/n): ");
sm_check(__FILE__, __LINE__, False);
}
+/*
+ * This test attempts to re-read a block written by Bacula
+ * normally at the end of the tape. Bacula will then back up
+ * over the two eof marks, backup over the record and reread
+ * it to make sure it is valid. Bacula can skip this validation
+ * if you set "Backward space record = no"
+ */
static int re_read_block_test()
{
DEV_BLOCK *block;
int stat = 0;
int len;
- if (!(dev->capabilities & CAP_EOM)) {
- Pmsg0(-1, _("Skipping read backwards test because MT_EOM turned off.\n"));
+ if (!(dev->capabilities & CAP_BSR)) {
+ Pmsg0(-1, _("Skipping read backwards test because BSR turned off.\n"));
return 0;
}
- Pmsg0(-1, _("\nWrite, backup, and re-read test.\n\n"
+ Pmsg0(-1, _("\n=== Write, 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"));
+ "then backup over the eof's and re-read the last record.\n"
+ "Bacula does this after writing the last block on the\n"
+ "tape to verify that the block was written correctly.\n"
+ "It is not an *essential* feature ...\n\n"));
rewindcmd();
block = new_block(dev);
rec = new_record();
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
} else {
- Pmsg1(0, _("Wrote fourth record of %d bytes.\n"), rec->data_len);
+ Pmsg1(0, _("Wrote third record of %d bytes.\n"), rec->data_len);
}
weofcmd();
weofcmd();
}
for (int i=0; i<len; i++) {
if (rec->data[i] != 3) {
- Pmsg0(0, _("Bad data in record. Test failed!\n"));
- Pmsg0(0, _("You might try adding:\n\n"
- "Hardware End of File = No\n\n"
+ Pmsg0(0, _("Bad data in record. Test failed!\n"
+ "This is not terribly serious since Bacula only uses\n"
+ "This function to verify the last block written to the\n"
+ "tape. Bacula will skip the last block verification\n"
+ "if you add:\n\n"
+ "Backward Space Record = No\n\n"
"to your Storage daemon's Device resource definition.\n"));
goto bail_out;
}
}
- Pmsg0(0, _("Re-read test succeeded!\n\n"));
+ Pmsg0(0, _("\nBlock re-read correct. Test succeeded!\n"));
+ Pmsg0(-1, _("=== End Write, backup, and re-read test ===\n\n"));
+
stat = 1;
bail_out:
return stat;
}
+/*
+ * This test writes some records, then writes an end of file,
+ * rewinds the tape, moves to the end of the data and attepts
+ * to append to the tape. This function is essential for
+ * Bacula to be able to write multiple jobs to the tape.
+ */
static int append_test()
{
- Pmsg0(-1, _("\n\n=== Append files test. ===\n\n"
+ Pmsg0(-1, _("\n\n=== Append files test ===\n\n"
+ "This test is essential to Bacula.\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"));
rewindcmd();
Pmsg0(0, _("Now moving to end of media.\n"));
eodcmd();
- Pmsg2(-1, _("End Append files test.\n\
-We should be in file 3. I am at file %d. This is %s\n\n"),
+ Pmsg2(-1, _("We should be in file 3. I am at file %d. This is %s\n"),
dev->file, dev->file == 3 ? "correct!" : "NOT correct!!!!");
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;
+ return -1;
}
- Pmsg0(-1, _("\nNow I am going to attempt to append to the tape.\n"));
+ Pmsg0(-1, _("\nNow the important part, I am going to attempt to append to the tape.\n\n"));
wrcmd();
weofcmd();
rewindcmd();
- Pmsg0(0, _("Done writing, scanning results ...\n\n"));
+ Pmsg0(-1, _("Done appending, there should be no I/O errors\n\n"));
+ Pmsg0(-1, "Doing Bacula scan of blocks:\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,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"));
+ Pmsg0(-1, _("End scanning the tape.\n"));
+ Pmsg2(-1, _("We should be in file 4. I am at file %d. This is %s\n"),
+ dev->file, dev->file == 4 ? "correct!" : "NOT correct!!!!");
- return 1;
-}
+ if (dev->file != 4) {
+ return -2;
+ }
-void append_block_test()
-{
- 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();
- rewindcmd();
- eodcmd();
- 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"));
- wrcmd();
- weofcmd();
- rewindcmd();
- 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"));
+ 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();
+ int stat;
- if (!append_test()) {
- return;
+ stat = append_test();
+ if (stat == 1) { /* OK get out */
+ goto all_done;
+ }
+ if (stat == -1) { /* first test failed */
+ if (dev_cap(dev, CAP_EOM)) {
+ Pmsg0(-1, "\nAppend test failed. Attempting again.\n"
+ "Setting \"Hardware End of Medium = no\" and retrying append test.\n\n");
+ dev->capabilities &= ~CAP_EOM; /* turn off eom */
+ stat = append_test();
+ if (stat == 1) {
+ Pmsg0(-1, "\n\nIt looks like the test worked this time, please add:\n\n"
+ " Hardware End of Medium = No\n\n"
+ "to your Device resource in the Storage conf file.\n");
+ goto all_done;
+ }
+ if (stat == -1) {
+ Pmsg0(-1, "\n\nThat appears not to have corrected the problem.\n");
+ goto all_done;
+ }
+ /* Wrong count after append */
+ if (stat == -2) {
+ Pmsg0(-1, "\n\nIt looks like the append failed. Attempting again.\n"
+ "Setting \"BSF at EOM = yes\" and retrying append test.\n");
+ dev->capabilities |= CAP_BSFATEOM; /* backspace on eom */
+ stat = append_test();
+ if (stat == 1) {
+ Pmsg0(-1, "\n\nIt looks like the test worked this time, please add:\n\n"
+ " Hardware End of Medium = No\n"
+ " BSR at EOM = yes\n\n"
+ "to your Device resource in the Storage conf file.\n");
+ goto all_done;
+ }
+ }
+
+ Pmsg0(-1, "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
+ "Unable to correct the problem. You MUST fix this\n"
+ "problem before Bacula can use your tape drive correctly\n");
+ Pmsg0(-1, "\nPerhaps running Bacula in fixed block mode will work.\n"
+ "Do so 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"
+ "This, however, is not really an ideal solution.\n");
+ }
}
- append_block_test();
+all_done:
+ Pmsg0(-1, _("\nThe above Bacula scan should have output identical to what follows.\n"
+ "Please double check it ...\n"
+ "=== Sample correct output ===\n"
+ "1 block of 64448 bytes in file 1\n"
+ "End of File mark.\n"
+ "2 blocks of 64448 bytes in file 2\n"
+ "End of File mark.\n"
+ "3 blocks of 64448 bytes in file 3\n"
+ "End of File mark.\n"
+ "1 block of 64448 bytes in file 4\n"
+ "End of File mark.\n"
+ "Total files=4, blocks=7, bytes = 451136\n"
+ "=== End sample correct output ===\n\n"));
+
+ Pmsg0(-1, _("If the above scan output is not identical to the\n"
+ "sample output, you MUST correct the problem\n"
+ "or Bacula will not be able to write multiple Jobs to \n"
+ "the tape.\n\n"));
+ if (stat == 1) {
+ re_read_block_test();
+ }
+ Pmsg0(-1, _("\n=== End Append files test ===\n"));
+
}
/* Forward space a file */
Pmsg0(0, "Forward spaced one record.\n");
}
-/* DEPRECATED DO NOT USE */
-static void rdcmd()
-{
-#ifdef xxxxx
- int stat;
-
- if (!read_dev(dev, buf, 512*126)) {
- Pmsg1(0, "Bad status from read. ERR=%s\n", strerror_dev(dev));
- return;
- }
- Pmsg1(10, "Read %d bytes\n", stat);
-#else
- printf("Rdcmd no longer implemented.\n");
-#endif
-}
-
/*
* Write a Bacula block to the tape
sm_check(__FILE__, __LINE__, False);
}
+/*
+ * Read a record from the tape
+ */
+static void rrcmd()
+{
+ char *buf;
+ int stat, len;
+
+ if (!get_cmd("Enter length to read: ")) {
+ return;
+ }
+ len = atoi(cmd);
+ if (len < 0 || len > 1000000) {
+ Pmsg0(0, _("Bad length entered, using default of 1024 bytes.\n"));
+ len = 1024;
+ }
+ buf = (char *)malloc(len);
+ stat = read(dev->fd, buf, len);
+ if (stat > 0 && stat <= len) {
+ errno = 0;
+ }
+ Pmsg3(0, _("Read of %d bytes gives stat=%d. ERR=%s\n"),
+ len, stat, strerror(errno));
+ free(buf);
+}
+
/*
* Scan tape by reading block by block. Report what is
{"label", labelcmd, "write a Bacula label to the tape"},
{"load", loadcmd, "load a tape"},
{"quit", quitcmd, "quit btape"},
- {"rd", rdcmd, "read tape"},
{"readlabel", readlabelcmd, "read and print the Bacula tape label"},
{"rectest", rectestcmd, "test record handling functions"},
{"rewind", rewindcmd, "rewind the tape"},
{"status", statcmd, "print tape status"},
{"test", testcmd, "General test Bacula tape functions"},
{"weof", weofcmd, "write an EOF on the tape"},
- {"wr", wrcmd, "write a single record of 2048 bytes"},
+ {"wr", wrcmd, "write a single Bacula block"},
+ {"rr", rrcmd, "read a single record"},
};
#define comsize (sizeof(commands)/sizeof(struct cmdstruct))