Date: Wed, 15 Nov 2000 17:15:20 -0800 (PST) From: Matthew Jacob <mjacob@feral.com> To: "Jacques A. Vidrine" <n@nectar.com> Cc: freebsd-scsi@FreeBSD.ORG Subject: Re: [ TAPE TIMEOUT] Re: afio & SCB 0xc - timed out while idle Message-ID: <Pine.BSF.4.21.0011151659250.96707-100000@beppo.feral.com> In-Reply-To: <20001115183155.A11050@hamlet.nectar.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Hmm. Save me some time/grief and check whether your tape drive is happy under freebsd. Take the program below, compile it, put a scratch tape in the drive, execute 'mt -f /dev/nrsa0 status' (and send us the output) and then execute: pat_test v -b 64k -r 1000 -n 10 -f /dev/nrsa0 and send the output. /* * Copyright (c) 2000 by Matthew Jacob. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice immediately at the beginning of the file, without modification, * this list of conditions, and the following disclaimer. * * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <errno.h> #include <sys/time.h> #include <sys/mtio.h> #ifndef roundup #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */ #endif static int szarg(char *); static __inline void filbuf(void *, int, int, int); static __inline int chkbuf(void *, int, int, int); static int rewind_tape(char *); static int szarg(char *n) { register int mult = 1; register char *q = n; while (*q != (char) 0) q++; --q; if (*q == 'k' || *q == 'K') { mult = 1024; *q = 0; } else if (*q == 'm' || *q == 'M') { mult = 1024 * 1024; *q = 0; } return (atoi(n) * mult); } static __inline void filbuf(void *buffer, int fileno, int recno, int blksiz) { int i; u_int64_t *lb = buffer; u_int64_t tseed = ((u_int64_t)fileno << 40) | ((u_int64_t)recno << 24); for (i = 0; i < (blksiz / (sizeof (u_int64_t))); i++) { lb[i] = tseed | i; } } static __inline int chkbuf(void *buffer, int fileno, int recno, int blksiz) { register int i; u_int64_t *lb = buffer; u_int64_t tseed = ((u_int64_t)fileno << 40) | ((u_int64_t)recno << 24); for (i = 0; i < (blksiz / (sizeof (u_int64_t))); i++) { if (lb[i] != (tseed | i)) { fprintf(stdout, "compare error at file %d, record %d, offset %d\n", fileno, recno, i * sizeof (u_int64_t)); fprintf(stdout, "Should be 0x%llx, got 0x%llx\n", tseed | i, lb[i]); return (i+1); } } return (0); } static int rewind_tape(char *file) { struct mtop mtop; int fd = open(file, O_RDONLY); if (fd < 0) { perror(file); return (-1); } mtop.mt_op = MTREW; mtop.mt_count = 1; if (ioctl(fd, MTIOCTOP, &mtop) < 0) { perror("MTREW"); return (-1); } if (close(fd) < 0) { perror("close"); return (-1); } return (0); } int main(int argc, char **argv) { const char *usage = "[ -v ] [ -b blksize ] [ -r blocks per file ] " "[ -n number-of-files ] -f no-rewinding-tape-drive"; time_t stime, etime; int blksize, recperfile, nfiles; char *file, *bp; u_int64_t nw, nr; int fd, c, wrecno, wfileno, rrecno, rfileno, verbose, last_recno; int w, r, lastw, lastr, nzr; nw = nr = 0; lastw = lastr = 0; w = wrecno = rrecno = last_recno = 0; nfiles = -1; recperfile = 1000; blksize = 32 << 10; file = NULL; verbose = 0; while ((c = getopt(argc, argv, "b:r:n:f:v")) != -1) { switch (c) { case 'b': blksize = szarg(optarg); break; case 'r': recperfile = atoi(optarg); break; case 'n': nfiles = atoi(optarg); break; case 'f': file = optarg; break; case 'v': verbose++; break; default: fprintf(stderr, "%s: %s\n", argv[0], usage); exit(1); } } setbuf(stdout, NULL); /* * Make sure tape can be opened (and rewound) */ if (file == NULL) { fprintf(stderr, "%s: %s\n", argv[0], usage); exit(1); } if (verbose) fprintf(stdout, ".......Rewind Tape\n"); if (rewind_tape(file) < 0) { exit(1); } /* * Allocate Buffer */ blksize &= ~(sizeof (u_int64_t) - 1); bp = calloc(blksize / sizeof (u_int64_t), sizeof (u_int64_t)); if (bp == NULL) { perror("calloc"); exit(1); } /* * Do write pass. */ if (verbose) fprintf(stdout, "........Write Pass\n"); time(&stime); wfileno = 0; for (;;) { fd = open(file, O_RDWR); if (fd < 0) { perror(file); w = 0; break; } for (wrecno = 0; wrecno < recperfile; wrecno++) { filbuf(bp, wfileno, wrecno, blksize); if ((w = write(fd, bp, blksize)) > 0) { nw += w; lastw = w; } if (verbose > 2) { fprintf(stdout, "Wrote File %d Record %d w=%d\n", wfileno, wrecno, w); } if (w != blksize) { break; } } if ((verbose && ((wfileno+1) & 0xf) == 0) || verbose > 1) { fprintf(stdout, "End of File %d (%lld total bytes written)\n", wfileno, nw); } if (w != blksize) { (void) close(fd); break; } if (close(fd) < 0) { perror("close"); w = 0; break; } if (nfiles > 0 && wfileno == nfiles-1) { break; } wfileno++; } time(&etime); if (w < 0) { perror("write"); w = 0; } fprintf(stdout, "EOT at File %d Record %d Offset %d (%lld total bytes written)\n", wfileno, wrecno, w, nw); etime -= stime; fprintf(stdout, "Elapsed Seconds: %ld; Data Rate: %gMB/s\n", (long) etime, ((double) (nw >> 20)) / ((double) etime)); /* * Rewind tape. */ if (verbose) fprintf(stdout, ".......Rewind Tape\n"); if (rewind_tape(file) < 0) { exit(1); } /* * Do read pass */ if (verbose) fprintf(stdout, ".........Read Pass\n"); time(&stime); for (nzr = 0, rfileno = 0;; rfileno++) { fd = open(file, O_RDONLY); if (fd < 0) { perror(file); r = 0; break; } for (rrecno = 0;; rrecno++) { if ((r = read(fd, bp, blksize)) > 0) { last_recno = rrecno; nzr = 0; nr += r; lastr = r; if (chkbuf(bp, rfileno, rrecno, r)) { exit(1); } } if (verbose > 2) { fprintf(stdout, "Read File %d Record %d w=%d\n", rfileno, rrecno, r); } if (r != blksize) { break; } if (rrecno > recperfile) { fprintf(stdout, "read more records per file " "(%d) than written (%d)\n", rrecno, recperfile); exit(1); } } if ((verbose && ((rfileno+1) & 0xf) == 0) || verbose > 1) { fprintf(stdout, "End of File %d (%lld total bytes read)\n", rfileno, nr); } /* * We can't break out of this loop on just plain * zero length reads- because those signal an * EOF condition- not EOT. We have to wait until * we get an error or two zero length reads in a row */ if (r == 0) { if (nzr++) { (void) close(fd); break; } else { rrecno = last_recno; } } else if (r < 0) { if (rrecno == 0) rrecno = last_recno; (void) close(fd); break; } if (close(fd) < 0) { perror("close"); r = 0; break; } } time(&etime); if (r < 0) { perror("read"); r = 0; } fprintf(stdout, "EOT at File %d Record %d Offset %d (%lld total bytes read)\n", rfileno, rrecno, r, nr); etime -= stime; fprintf(stdout, "Elapsed Seconds: %ld: Data Rate: %gMB/s\n", (long) etime, ((double) (nr >> 2) / ((double) etime))); return (0); } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-scsi" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0011151659250.96707-100000>