]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/btape.c
This commit was manufactured by cvs2svn to create tag
[bacula/bacula] / bacula / src / stored / btape.c
index 9062465fdd899cc10b6b2f9b0ce5a78025301671..99ddfa7a91c0ccdf759551489dfdd17ead874fc0 100644 (file)
@@ -149,9 +149,9 @@ int main(int margc, char *margv[])
    char buf[1000];
 
    /* Sanity checks */
-   if (TAPE_BSIZE % DEV_BSIZE != 0 || TAPE_BSIZE / DEV_BSIZE == 0) {
+   if (TAPE_BSIZE % B_DEV_BSIZE != 0 || TAPE_BSIZE / B_DEV_BSIZE == 0) {
       Emsg2(M_ABORT, 0, "Tape block size (%d) not multiple of system size (%d)\n",
-        TAPE_BSIZE, DEV_BSIZE);
+        TAPE_BSIZE, B_DEV_BSIZE);
    }
    if (TAPE_BSIZE != (1 << (ffs(TAPE_BSIZE)-1))) {
       Emsg1(M_ABORT, 0, "Tape block size (%d) is not a power of 2\n", TAPE_BSIZE);
@@ -333,6 +333,7 @@ static bool open_the_device()
       }
    }
    Pmsg1(000, "open_dev %s OK\n", dev_name(dev));
+   dev->state |= ST_APPEND;
    unlock_device(dev);
    free_block(block);
    return true;
@@ -543,6 +544,7 @@ static void capcmd()
    printf("%sFSR ", dev->capabilities & CAP_FSR ? "" : "!");
    printf("%sFSF ", dev->capabilities & CAP_FSF ? "" : "!");
    printf("%sFASTFSF ", dev->capabilities & CAP_FASTFSF ? "" : "!");
+   printf("%sBSFATEOM ", dev->capabilities & CAP_BSFATEOM ? "" : "!");
    printf("%sEOM ", dev->capabilities & CAP_EOM ? "" : "!");
    printf("%sREM ", dev->capabilities & CAP_REM ? "" : "!");
    printf("%sRACCESS ", dev->capabilities & CAP_RACCESS ? "" : "!");
@@ -705,12 +707,14 @@ static int re_read_block_test()
    }
    Pmsg0(0, "Backspace record OK.\n");
    if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
-      Pmsg1(0, _("Read block failed! ERR=%s\n"), strerror(dev->dev_errno));
+      berrno be;
+      Pmsg1(0, _("Read block failed! ERR=%s\n"), be.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));
+      berrno be;
+      Pmsg1(0, _("Read block failed! ERR=%s\n"), be.strerror(dev->dev_errno));
       goto bail_out;
    }
    for (int i=0; i<len; i++) {
@@ -809,16 +813,20 @@ static int write_read_test()
    for (i=1; i<=2000; i++) {
 read_again:
       if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
+        berrno be;
         if (dev_state(dev, ST_EOF)) {
             Pmsg0(-1, _("Got EOF on tape.\n"));
-           goto read_again;
+           if (i == 1001) {
+              goto read_again;
+           }
         }
-         Pmsg1(0, _("Read block failed! ERR=%s\n"), strerror(dev->dev_errno));
+         Pmsg2(0, _("Read block %d failed! ERR=%s\n"), i, be.strerror(dev->dev_errno));
         goto bail_out;
       }
       memset(rec->data, 0, rec->data_len);
       if (!read_record_from_block(block, rec)) {
-         Pmsg1(0, _("Read record failed! ERR=%s\n"), strerror(dev->dev_errno));
+        berrno be;
+         Pmsg2(0, _("Read record failed. Block %d! ERR=%s\n"), i, be.strerror(dev->dev_errno));
         goto bail_out;
       }
       p = (int *)rec->data;
@@ -857,6 +865,7 @@ static int position_test()
    int recno = 0;
    int file = 0, blk = 0;
    int *p;
+   bool got_eof = false;
 
    Pmsg0(-1, _("\n=== Write, rewind, and position test ===\n\n"
       "I'm going to write 1000 records and an EOF\n"
@@ -958,20 +967,33 @@ static int position_test()
       }
 read_again:
       if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
+        berrno be;
         if (dev_state(dev, ST_EOF)) {
             Pmsg0(-1, _("Got EOF on tape.\n"));
-           goto read_again;
+           if (!got_eof) {
+              got_eof = true;
+              goto read_again;
+           }
         }
-         Pmsg1(0, _("Read block failed! ERR=%s\n\n"), strerror(dev->dev_errno));
+         Pmsg4(0, _("Read block %d failed! file=%d blk=%d. ERR=%s\n\n"), 
+           recno, file, blk, be.strerror(dev->dev_errno));
          Pmsg0(0, _("This may be because the tape drive block size is not\n"
                     " set to variable blocking as normally used by Bacula.\n"
                     " Please see the Tape Testing chapter in the manual and \n"
-                    " look for using mt with defblksize and setoptions\n"));
+                    " look for using mt with defblksize and setoptions\n"
+                    "If your tape drive block size is correct, then perhaps\n"
+                    " your SCSI driver is *really* stupid and does not\n"
+                    " correctly report the file:block after a FSF. In this\n"
+                    " case try setting:\n"
+                    "    Fast Forward Space File = no\n"
+                    " in your Device resource.\n"));
+
         goto bail_out;
       }
       memset(rec->data, 0, rec->data_len);
       if (!read_record_from_block(block, rec)) {
-         Pmsg1(0, _("Read record failed! ERR=%s\n"), strerror(dev->dev_errno));
+        berrno be;
+         Pmsg1(0, _("Read record failed! ERR=%s\n"), be.strerror(dev->dev_errno));
         goto bail_out;
       }
       p = (int *)rec->data;
@@ -982,7 +1004,7 @@ read_again:
            goto bail_out;
         }
       }
-      Pmsg0(-1, _("Block re-read correctly.\n"));
+      Pmsg1(-1, _("Block %d re-read correctly.\n"), recno);
    }
    Pmsg0(-1, _("=== Test Succeeded. End Write, rewind, and re-read test ===\n\n"));
    stat = 1;
@@ -1104,9 +1126,8 @@ try_again:
       loaded = atoi(results);
    } else {
       berrno be;
-      be.set_errno(status);
       Pmsg1(-1, _("3991 Bad autochanger command: %s\n"), changer);
-      Pmsg2(-1, _("3991 result=\"%s\": ERR=%s\n"), results, be.strerror());
+      Pmsg2(-1, _("3991 result=\"%s\": ERR=%s\n"), results, be.strerror(status));
       goto bail_out;
    }
    if (loaded) {
@@ -1128,9 +1149,8 @@ try_again:
       Pmsg2(-1, "unload status=%s %d\n", status==0?"OK":"Bad", status);
       if (status != 0) {
         berrno be;
-        be.set_errno(status);
          Pmsg1(-1, _("3992 Bad autochanger command: %s\n"), changer);
-         Pmsg2(-1, _("3992 result=\"%s\": ERR=%s\n"), results, be.strerror());
+         Pmsg2(-1, _("3992 result=\"%s\": ERR=%s\n"), results, be.strerror(status));
       }
    }
 
@@ -1151,9 +1171,8 @@ try_again:
         slot, dev->drive_index);
    } else {
       berrno be;
-      be.set_errno(status);
       Pmsg1(-1, _("3993 Bad autochanger command: %s\n"), changer);
-      Pmsg2(-1, _("3993 result=\"%s\": ERR=%s\n"), results, be.strerror());
+      Pmsg2(-1, _("3993 result=\"%s\": ERR=%s\n"), results, be.strerror(status));
       goto bail_out;
    }
 
@@ -1513,8 +1532,9 @@ static void rrcmd()
    if (stat > 0 && stat <= len) {
       errno = 0;
    }
+   berrno be;
    Pmsg3(0, _("Read of %d bytes gives stat=%d. ERR=%s\n"),
-      len, stat, strerror(errno));
+      len, stat, be.strerror());
    free(buf);
 }
 
@@ -1544,9 +1564,10 @@ static void scancmd()
    Pmsg1(0, _("Starting scan at file %u\n"), dev->file);
    for (;;) {
       if ((stat = read(dev->fd, buf, sizeof(buf))) < 0) {
+        berrno be;
         clrerror_dev(dev, -1);
          Mmsg2(dev->errmsg, "read error on %s. ERR=%s.\n",
-           dev->dev_name, strerror(dev->dev_errno));
+           dev->dev_name, be.strerror());
          Pmsg2(0, "Bad status from read %d. ERR=%s\n", stat, strerror_dev(dev));
         if (blocks > 0)
             printf("%d block%s of %d bytes in file %d\n",        
@@ -1747,6 +1768,11 @@ This may take a long time -- hours! ...\n\n");
    /* Use fixed block size to simplify read back */
    min_block_size = dev->min_block_size;
    dev->min_block_size = dev->max_block_size;
+   set_volume_name("TestVolume1", 1);
+
+   rewind_dev(dev);
+   weof_dev(dev, 1);
+   dev->state &= ~ST_APPEND;         /* force volume to be relabeled */
 
    /* 
     * Acquire output device for writing.  Note, after acquiring a
@@ -1770,7 +1796,7 @@ This may take a long time -- hours! ...\n\n");
         strerror_dev(dev));
       ok = false;
    }
-   Pmsg0(-1, "Wrote Start Of Session label.\n");
+   Pmsg0(-1, "Wrote Start of Session label.\n");
 
    memset(&rec, 0, sizeof(rec));
    rec.data = get_memory(100000);     /* max record size */
@@ -1890,7 +1916,7 @@ This may take a long time -- hours! ...\n\n");
          Pmsg0(-1, _("Set ok=false after write_block_to_device.\n"));
         ok = false;
       }
-      Pmsg0(-1, _("Wrote End Of Session label.\n"));
+      Pmsg0(-1, _("Wrote End of Session label.\n"));
 
       /* Save last block info for second tape */
       last_block_num2 = last_block_num;
@@ -1917,18 +1943,20 @@ This may take a long time -- hours! ...\n\n");
       Pmsg2(-1, "Wrote state file last_block_num1=%d last_block_num2=%d\n",
         last_block_num1, last_block_num2);
    } else {
+      berrno be;
       Pmsg2(-1, _("Could not create state file: %s ERR=%s\n"), buf,
-                strerror(errno));
+                be.strerror());
    }
 
-   /* Release the device if multiple tapes being used */
-   if (!simple && !release_device(jcr)) {
-      Pmsg0(-1, _("Error in release_device\n"));
-      ok = false;
-   }
+   Pmsg4(-1, _("\n\nDone filling tape%s at %d:%d. Now beginning re-read of %stape ...\n"),
+      simple?"":"s", jcr->dcr->dev->file, jcr->dcr->dev->block_num, simple?"":"first ");
 
-   Pmsg2(-1, _("\n\nDone filling tape%s. Now beginning re-read of %stape ...\n"),
-      simple?"":"s", simple?"":"first ");
+   jcr->dcr->block = block;
+   /* Release the device if multiple tapes being used */
+// if (!simple && !release_device(jcr)) {
+//    Pmsg0(-1, _("Error in release_device\n"));
+//    ok = false;
+// }
 
    do_unfill();
 
@@ -1969,8 +1997,9 @@ static void unfillcmd()
          return;
        }
    } else {
+      berrno be;
       Pmsg2(-1, "\nCould not find the state file: %s ERR=%s\n"
-             "You must redo the fill command.\n", buf, strerror(errno));
+             "You must redo the fill command.\n", buf, be.strerror());
       return;
    }
    do_unfill();
@@ -2019,7 +2048,8 @@ static void do_unfill()
       jcr->bsr = NULL;
       create_vol_list(jcr);
       close_dev(dev);
-      dev->state &= ~ST_READ;
+      dev->state &= ~(ST_READ|ST_APPEND);
+      dev->num_writers = 0;
       if (!acquire_device_for_read(jcr)) {
          Pmsg1(-1, "%s", dev->errmsg);
         goto bail_out;
@@ -2030,14 +2060,18 @@ static void do_unfill()
     * Note, re-reading last block may have caused us to 
     *  loose track of where we are (block number unknown).
     */
-   rewind_dev(dev);                  /* get to a known place on tape */
+   if (!rewind_dev(dev)) {               /* get to a known place on tape */
+      goto bail_out;
+   }
    /* Read the first 1000 records */
    Pmsg0(-1, _("Reading the first 1000 records.\n"));
+   quickie_count = 0;
    read_records(dcr, quickie_cb, my_mount_next_read_volume);
    Pmsg4(-1, _("Reposition from %u:%u to %u:%u\n"), dev->file, dev->block_num,
         last_file, last_block_num);
    if (!reposition_dev(dev, last_file, last_block_num)) {
       Pmsg1(-1, "Reposition error. ERR=%s\n", strerror_dev(dev));
+      goto bail_out;
    }
    Pmsg1(-1, _("Reading block %u.\n"), last_block_num);
    if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
@@ -2124,8 +2158,17 @@ bail_out:
 /* Read 1000 records then stop */
 static bool quickie_cb(DCR *dcr, DEV_RECORD *rec)
 {
+   DEVICE *dev = dcr->dev;
+   if (dev->file != 0) {
+      Pmsg3(-1, "ERROR! device at %d:%d count=%d\n", dev->file, dev->block_num,
+        quickie_count);
+      return false;
+   }
    quickie_count++;
-   return quickie_count <= 1000;
+   if (quickie_count == 1000) {
+      Pmsg2(-1, "1000 records read now at %d:%d\n", dev->file, dev->block_num);
+   }
+   return quickie_count < 1000;
 }
 
 static bool compare_blocks(DEV_BLOCK *last_block, DEV_BLOCK *block) 
@@ -2175,10 +2218,10 @@ static bool compare_blocks(DEV_BLOCK *last_block, DEV_BLOCK *block)
 static int flush_block(DEV_BLOCK *block, int dump)
 {
    char ec1[50];
-   lock_device(dev);
    DEV_BLOCK *tblock;
    uint32_t this_file, this_block_num;
 
+   lock_device(dev);
    if (!this_block) {
       this_block = new_block(dev);
    }
@@ -2222,7 +2265,8 @@ static int flush_block(DEV_BLOCK *block, int dump)
       }
       kbs = (double)dev->VolCatInfo.VolCatBytes / (1000 * now);
       vol_size = dev->VolCatInfo.VolCatBytes;
-      Pmsg2(000, "End of tape. VolumeCapacity=%s. Write rate = %.1f KB/s\n", 
+      Pmsg4(000, "End of tape %d:%d. VolumeCapacity=%s. Write rate = %.1f KB/s\n", 
+        dev->file, dev->block_num,
         edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, ec1), kbs);
 
       if (simple) {
@@ -2245,7 +2289,8 @@ static int flush_block(DEV_BLOCK *block, int dump)
    memcpy(this_block->buf, block->buf, this_block->buf_len);
 
    /*
-    * Toggle between two allocated blocks for efficiency.
+    * Note, we always read/write to block, but we toggle
+    *  copying it to one or another of two allocated blocks.
     * Switch blocks so that the block just successfully written is
     *  always in last_block. 
     */
@@ -2358,8 +2403,9 @@ static void rawfill_cmd()
    }
    my_errno = errno;
    printf("\n");
+   berrno be;
    printf("Write failed at block %u. stat=%d ERR=%s\n", block_num, stat,
-      strerror(my_errno));
+      be.strerror(my_errno));
    weofcmd();
 }