Jon LaBadie's Mail:
> On Wed, Mar 12, 2008 at 04:00:00PM +0100, Paul Bijnens wrote:
[...]
> > I seem to remember there was indeed a problem on some hosts
> > where rewind flagged success and finished, but the tape drive
> > was actually not ready to accept new requests, resulting in IO errors
> > until the tape was fully rewound.
> >
> > But I do not remember anymore if or how it can be solved
> > (except by modifying the code and waiting longer after the rewind).
> >
>
> I was in that situation with a DDS3, 6 tape, tapechanger from HP.
> I ran amanda's use of mt and mtx through wrappers and inserted
> sleeps for various cmds (notably rewinds for up to 20 or 30 sec.)
> and I put in some repeats for things like status checks that
> failed the first time.
Back in May 2007 myselph wrote:
> I had a similar problem with with a DDS3 tape drive (HP-C1537A) connected
> to my alpha running (at that time) DU 4.0d. It seemed to me that the
> drive / driver returns immediately after a rewind operation, but a
> following write on the same (kept-open) filedescriptor returns
> unsuccessfully if the rewind did not complete yet. Amtapetype exactly
> does this.
>
> The situation was not reproducible in my setup by a sequence of shell
> commands (like ``mt rewind; tar -c ...''), as each shell command is an own
> process and opens its own filedescriptor for accessing the tape.
The problem also existed after my box having been updated to Tru64 5.1B-3.
The attached patch (relative to 2.5.2) fixed the problem for me.
In June Ian Turner contacted me for testing alternative solutions
for the rewind / timeout / IO error problem, but on Tru64 only the
open / close workaround was fully successful.
I don't know, if the workaround has been integrated in more recent
versions of amanda.
Regards
\franz
--- amanda-2.5.2-20070523/tape-src/tapetype.c.orig Fri May 4 13:39:08 2007
+++ amanda-2.5.2-20070523/tape-src/tapetype.c Wed May 30 09:30:24 2007
@@ -59,8 +59,9 @@
static int writeblock(int fd);
static off_t writeblocks(int fd, off_t nblks);
static void allocrandombytes(void);
-static void do_pass0(off_t size, time_t *seconds, int dorewind);
-static void do_pass(off_t size, off_t *blocks, off_t *files, time_t *seconds);
+static void do_pass0(off_t size, time_t *seconds, int dorewind, char *tapedev);
+static void do_pass(off_t size, off_t *blocks, off_t *files, time_t *seconds,
+ char *tapedev);
static void help(void);
static void initnotrandombytes(void);
static void initrandombytes(void);
@@ -143,7 +144,10 @@
if ((w = tapefd_write(fd, getrandombytes(), blocksize)) ==
(ssize_t)blocksize) {
return 1;
}
- if (w >= 0) {
+ /*
+ fprintf(stderr, "\nwriteblock(): w=%d, errno=%d\n", w, errno);
+ */
+ if (w != (size_t) -1) {
short_write = 1;
} else {
short_write = 0;
@@ -222,7 +226,8 @@
off_t size,
off_t * blocks,
off_t * files,
- time_t * seconds)
+ time_t * seconds,
+ char * tapedev)
{
off_t blks;
time_t start, end;
@@ -233,6 +238,12 @@
sProgName, tapedev, strerror(errno));
exit(1);
}
+ if (((-1 == tapefd_close(fd)) ||
+ (-1 == (fd = tape_open(tapedev, O_RDWR))))) {
+ fprintf(stderr, "%s: could not re-open %s: %s\n",
+ sProgName, tapedev, strerror(errno));
+ exit(1);
+ }
time(&start);
@@ -280,7 +291,8 @@
do_pass0(
off_t size,
time_t * seconds,
- int dorewind)
+ int dorewind,
+ char * tapedev)
{
off_t blks;
time_t start, end;
@@ -291,6 +303,13 @@
sProgName, tapedev, strerror(errno));
exit(1);
}
+ if (dorewind &&
+ ((-1 == tapefd_close(fd)) ||
+ (-1 == (fd = tape_open(tapedev, O_RDWR))))) {
+ fprintf(stderr, "%s: could not re-open %s: %s\n",
+ sProgName, tapedev, strerror(errno));
+ exit(1);
+ }
time(&start);
@@ -530,8 +549,8 @@
* first a dummy pass to rewind, stop, start and
* get drive streaming, then do the real timing
*/
- do_pass0(pass0size, &pass2time, 1);
- do_pass0(pass0size, &pass1time, 0);
+ do_pass0(pass0size, &pass2time, 1, tapedev);
+ do_pass0(pass0size, &pass1time, 0, tapedev);
if (pass0size >= (off_t)(10 * 1024 * 1024)) {
fprintf(stderr,
"\rTape device is too fast to detect hardware compression...\n");
@@ -552,8 +571,8 @@
initrandombytes();
fprintf(stderr, "Estimate phase 2...");
- do_pass0(pass0size, &pass2time, 1); /* rewind and get drive streaming */
- do_pass0(pass0size, &pass2time, 0);
+ do_pass0(pass0size, &pass2time, 1, tapedev); /* rewind and get drive
streaming */
+ do_pass0(pass0size, &pass2time, 0, tapedev);
fprintf(stderr, "\rWriting " OFF_T_FMT
" Mbyte uncompresseable data: " TIME_T_FMT " sec\n",
(OFF_T_FMT_TYPE)((off_t)blockkb * pass0size / (off_t)1024),
@@ -603,13 +622,13 @@
if(pass1size <= (off_t)0) {
pass1size = (off_t)2; /* strange end case */
}
- do_pass(pass1size, &pass1blocks, &pass1files, &pass1time);
+ do_pass(pass1size, &pass1blocks, &pass1files, &pass1time, tapedev);
/*
* Do pass 2 -- write smaller files until error.
*/
pass2size = pass1size / (off_t)2;
- do_pass(pass2size, &pass2blocks, &pass2files, &pass2time);
+ do_pass(pass2size, &pass2blocks, &pass2files, &pass2time, tapedev);
/*
* Compute the size of a filemark as the difference in data written