From 82d81317140c734d9d044df9f22c19150cd26b04 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Thu, 27 Mar 2003 15:15:41 +0000 Subject: [PATCH] Adapt to FreeBSD tape drives git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@399 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/stored/btape.c | 146 ++++++++++++++++++++++++-------- bacula/src/stored/dev.c | 44 +++++++--- bacula/src/stored/dev.h | 1 + bacula/src/stored/stored_conf.c | 1 + bacula/src/version.h | 4 +- 5 files changed, 150 insertions(+), 46 deletions(-) diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index a045aab6d7..ecb16f2506 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -57,8 +57,10 @@ static void scancmd(); 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); @@ -499,6 +501,14 @@ static void capcmd() 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(); + } /* @@ -607,7 +617,7 @@ static int re_read_block_test() 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(); @@ -687,13 +697,7 @@ static int append_test() dev->file, dev->file == 3 ? "correct!" : "NOT correct!!!!"); if (dev->file != 3) { - Pmsg0(-1, _("\nYou MUST correct this problem. Try adding:\n\n" - "Hardware End of Medium = No\n\n" - "to your Storage daemon's Device resource definition.\n" - "Then re-run this test. If it still fails, there is a\n" - "a problem with your tape driver that must be corrected\n" - "before continuing.\n")); - return 0; + return -1; } Pmsg0(-1, _("\nNow the important part, I am going to attempt to append to the tape.\n\n")); @@ -703,8 +707,77 @@ static int append_test() 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 scanning the tape.\n\n" - "The above scan should have output identical to what follows:\n\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!!!!"); + + if (dev->file != 4) { + return -2; + } + + return 1; +} + +/* + * This is a general test of Bacula's functions + * needed to read and write the tape. + */ +static void testcmd() +{ + int stat; + re_read_block_test(); + + 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"); + } + } + +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" @@ -720,30 +793,10 @@ static int append_test() 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 the output is incorrect, you might\n" - "be able to run 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" - "This, however, is not really an ideal solution.\n")); + "the tape.\n\n")); Pmsg0(-1, _("\n=== End Append files test ===\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(); - - if (!append_test()) { - return; - } + } /* Forward space a file */ @@ -808,6 +861,32 @@ bail_out: 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 @@ -1448,7 +1527,8 @@ static struct cmdstruct commands[] = { {"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)) diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index ac112d5e7c..11a9cd3fd3 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -412,7 +412,7 @@ eod_dev(DEVICE *dev) } return 0; } - if (dev->capabilities & CAP_EOM) { + if (dev_cap(dev, CAP_EOM)) { mt_com.mt_op = MTEOM; mt_com.mt_count = 1; if ((stat=ioctl(dev->fd, MTIOCTOP, (char *)&mt_com)) < 0) { @@ -447,9 +447,20 @@ eod_dev(DEVICE *dev) } } } - update_pos_dev(dev); /* update position */ + /* + * Some drivers leave us after second EOF when doing + * MTEOM, so we must backup so that appending overwrites + * the second EOF. + */ + if (dev_cap(dev, CAP_BSFATEOM)) { + stat = (bsf_dev(dev, 1) == 0); + dev->file++; /* keep same file */ + } else { + update_pos_dev(dev); /* update position */ + stat = 1; + } Dmsg1(200, "EOD dev->file=%d\n", dev->file); - return 1; + return stat; } /* @@ -663,7 +674,6 @@ fsf_dev(DEVICE *dev, int num) { struct mtop mt_com; int stat = 0; - char rbuf[1024]; if (dev->fd < 0) { dev->dev_errno = EBADF; @@ -680,26 +690,37 @@ fsf_dev(DEVICE *dev, int num) Mmsg1(&dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name); return 0; } - if (dev->state & ST_EOF) + if (dev->state & ST_EOF) { Dmsg0(200, "ST_EOF set on entry to FSF\n"); - if (dev->state & ST_EOT) + } + if (dev->state & ST_EOT) { Dmsg0(200, "ST_EOT set on entry to FSF\n"); + } Dmsg0(29, "fsf_dev\n"); dev->block_num = 0; - if (dev->capabilities & CAP_FSF) { + if (dev_cap(dev, CAP_FSF)) { + POOLMEM *rbuf; + int rbuf_len; Dmsg0(200, "FSF has cap_fsf\n"); + if (dev->max_block_size == 0) { + rbuf_len = DEFAULT_BLOCK_SIZE; + } else { + rbuf_len = dev->max_block_size; + } + rbuf = get_memory(rbuf_len); mt_com.mt_op = MTFSF; mt_com.mt_count = 1; while (num-- && !(dev->state & ST_EOT)) { - Dmsg0(200, "Doing read for fsf\n"); - if ((stat = read(dev->fd, rbuf, sizeof(rbuf))) < 0) { + Dmsg0(200, "Doing read before fsf\n"); + if ((stat = read(dev->fd, (char *)rbuf, rbuf_len)) < 0) { if (errno == ENOMEM) { /* tape record exceeds buf len */ - stat = sizeof(rbuf); /* This is OK */ + stat = rbuf_len; /* This is OK */ } else { dev->state |= ST_EOT; clrerror_dev(dev, -1); - Dmsg1(200, "Set ST_EOT read error %d\n", dev->dev_errno); + Dmsg2(200, "Set ST_EOT read errno=%d. ERR=%s\n", dev->dev_errno, + strerror(dev->dev_errno)); Mmsg2(&dev->errmsg, _("read error on %s. ERR=%s.\n"), dev->dev_name, strerror(dev->dev_errno)); Dmsg1(200, "%s", dev->errmsg); @@ -740,6 +761,7 @@ fsf_dev(DEVICE *dev, int num) dev->file_addr = 0; } } + free_memory(rbuf); /* * No FSF, so use FSR to simulate it diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index d2fd63c935..2d558d93b7 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -81,6 +81,7 @@ #define CAP_AUTOCHANGER 0x1000 /* AutoChanger */ #define CAP_OFFLINEUNMOUNT 0x2000 /* Offline before unmount */ #define CAP_STREAM 0x4000 /* Stream device */ +#define CAP_BSFATEOM 0x8000 /* Backspace file at EOM */ /* Test state */ #define dev_state(dev, state) ((dev)->state & (state)) diff --git a/bacula/src/stored/stored_conf.c b/bacula/src/stored/stored_conf.c index 864b0534ad..4fdb287020 100644 --- a/bacula/src/stored/stored_conf.c +++ b/bacula/src/stored/stored_conf.c @@ -86,6 +86,7 @@ static struct res_items dev_items[] = { {"hardwareendofmedium", store_yesno, ITEM(res_dev.cap_bits), CAP_EOM, ITEM_DEFAULT, 1}, {"backwardspacerecord", store_yesno, ITEM(res_dev.cap_bits), CAP_BSR, ITEM_DEFAULT, 1}, {"backwardspacefile", store_yesno, ITEM(res_dev.cap_bits), CAP_BSF, ITEM_DEFAULT, 1}, + {"bsfateom", store_yesno, ITEM(res_dev.cap_bits), CAP_BSFATEOM, ITEM_DEFAULT, 0}, {"forwardspacerecord", store_yesno, ITEM(res_dev.cap_bits), CAP_FSR, ITEM_DEFAULT, 1}, {"forwardspacefile", store_yesno, ITEM(res_dev.cap_bits), CAP_FSF, ITEM_DEFAULT, 1}, {"removablemedia", store_yesno, ITEM(res_dev.cap_bits), CAP_REM, ITEM_DEFAULT, 1}, diff --git a/bacula/src/version.h b/bacula/src/version.h index 3198dc40d2..ccad32fa8c 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #define VERSION "1.30" #define VSTRING "1" -#define BDATE "25 March 2003" -#define LSMDATE "25Mar03" +#define BDATE "27 March 2003" +#define LSMDATE "27Mar03" /* Debug flags */ #define DEBUG 1 -- 2.39.5