read() from a tape

chris at umcp-cs.UUCP chris at umcp-cs.UUCP
Sun Nov 13 10:47:20 AEST 1983


Re:  read () from a tape gives ridiculous return value.  Bug is on
4.1BSD and possibly other versions of Unix].

Welcome to the Wonderful World of Weirdness -- tape drives.  The
4.1BSD tm.c has a sign extension bug when filling in b->b_resid.
CVL has a fixed version of tm.c; here's a diff listing, with my
comments, and some irrelevant stuff (Digi-Data stuff, and some
error logging) removed.

*** /usr/src/sys/dev/tm.c	Fri Oct  9 17:24:17 1981 [4.1 version]
--- tm.c	Sat Nov 12 19:07:53 1983		[CVL's fixed version]
***************
This one looks like someone wasn't thinking...
*** 100,106
  	u_short	sc_dens;	/* prototype command with density info */
  	daddr_t	sc_timo;	/* time until timeout expires */
  	short	sc_tact;	/* timeout is active */
! } te_softc[NTM];
  #ifdef unneeded
  int	tmgapsdcnt;		/* DEBUG */
  #endif

--- 100,117 -----
  	u_short	sc_dens;	/* prototype command with density info */
  	daddr_t	sc_timo;	/* time until timeout expires */
  	short	sc_tact;	/* timeout is active */
! } te_softc[NTE];	/* was NTM - JIP, CVL, 12/30/82 */
  #ifdef unneeded
  int	tmgapsdcnt;		/* DEBUG */
  #endif
***************
Not all tape drives are the same speed...
*** 422,427
  		 * Set next state; give 5 minutes to complete
  		 * rewind, or 10 seconds per iteration (minimum 60
  		 * seconds and max 5 minutes) to complete other ops.
  		 */
  		if (bp->b_command == TM_REW) {
  			um->um_tab.b_active = SREW;

--- 433,440 -----
  		 * Set next state; give 5 minutes to complete
  		 * rewind, or 10 seconds per iteration (minimum 60
  		 * seconds and max 5 minutes) to complete other ops.
+ 		 * Changed to allow 30 seconds per iteration, 10 min max,
+ 		 *  with 10 min rewind JIP
  		 */
  		if (bp->b_command == TM_REW) {
  			um->um_tab.b_active = SREW;
***************
*** 425,431
  		 */
  		if (bp->b_command == TM_REW) {
  			um->um_tab.b_active = SREW;
! 			sc->sc_timo = 5 * 60;
  		} else {
  			um->um_tab.b_active = SCOM;
  			sc->sc_timo =

--- 438,444 -----
  		 */
  		if (bp->b_command == TM_REW) {
  			um->um_tab.b_active = SREW;
! 			sc->sc_timo = 10 * 60;
  		} else {
  			um->um_tab.b_active = SCOM;
  			sc->sc_timo =
***************
*** 429,435
  		} else {
  			um->um_tab.b_active = SCOM;
  			sc->sc_timo =
! 				imin(imax(10*(int)-bp->b_repcnt,60),5*60);
  		}
  		if (bp->b_command == TM_SFORW || bp->b_command == TM_SREV)
  			addr->tmbc = bp->b_repcnt;

--- 442,448 -----
  		} else {
  			um->um_tab.b_active = SCOM;
  			sc->sc_timo =
! 				imin(imax(30*(int)-bp->b_repcnt,60),10*60);
  		}
  		if (bp->b_command == TM_SFORW || bp->b_command == TM_SREV)
  			addr->tmbc = bp->b_repcnt;
***************
I'm not sure why this change... maybe it has something to do with the
error logging.  [note: I collapsed two diff entries]
*** 616,622
  		 * If we were reading raw tape and the only error was that the
  		 * record was too long, then we don't consider this an error.
  		 */
! 		if (bp == &rtmbuf[TMUNIT(bp->b_dev)] && (bp->b_flags&B_READ) &&
  		    (addr->tmer&(TMER_HARD|TMER_SOFT)) == TMER_RLE)
!  			goto ignoreerr;
  		/*

--- 635,641 -----
  		 * If we were reading raw tape and the only error was that the
  		 * record was too long, then we don't consider this an error.
  		 */
! /*		if (bp == &rtmbuf[TMUNIT(bp->b_dev)] && (bp->b_flags&B_READ) &&
  		    (addr->tmer&(TMER_HARD|TMER_SOFT)) == TMER_RLE)
!  			goto ignoreerr;		JIP CVL */
  		/*
***************
*** 629,635
  				ubadone(um);
  				goto opcont;
  			}
! 		} else
  			/*
  			 * Hard or non-i/o errors on non-raw tape
  			 * cause it to close.

--- 656,662 -----
  				ubadone(um);
  				goto opcont;
  			}
! 		} else {
  			/*
  			 * Hard or non-i/o errors on non-raw tape
  			 * cause it to close.
***************
*** 634,639
  			 * Hard or non-i/o errors on non-raw tape
  			 * cause it to close.
  			 */
  			if (sc->sc_openf>0 && bp != &rtmbuf[TMUNIT(bp->b_dev)])
  				sc->sc_openf = -1;
  		/*

--- 661,668 -----
  			 * Hard or non-i/o errors on non-raw tape
  			 * cause it to close.
  			 */
+ 	/* JIP CVL */	if ((addr->tmer&TMER_HARD)==0 &&
+ 				um->um_tab.b_errcnt) goto ignoreerr;
  			if (sc->sc_openf>0 && bp != &rtmbuf[TMUNIT(bp->b_dev)])
  				sc->sc_openf = -1;
  		}
***************
*** 636,641
  			 */
  			if (sc->sc_openf>0 && bp != &rtmbuf[TMUNIT(bp->b_dev)])
  				sc->sc_openf = -1;
  		/*
  		 * Couldn't recover error
  		 */

--- 665,671 -----
  				um->um_tab.b_errcnt) goto ignoreerr;
  			if (sc->sc_openf>0 && bp != &rtmbuf[TMUNIT(bp->b_dev)])
  				sc->sc_openf = -1;
+ 		}
  		/*
  		 * Couldn't recover error
  		 */
***************
[This here is your length error.]
*** 688,694
  	 */
  	um->um_tab.b_errcnt = 0;
  	dp->b_actf = bp->av_forw;
! 	bp->b_resid = -addr->tmbc;
  	ubadone(um);
  	iodone(bp);
  	/*

--- 729,739 -----
  	}
  #endif ERRORLOG
  	dp->b_actf = bp->av_forw;
! 	/* allow for long reads JIP */
! 	/* compiler bug!! casting as (short unsigned) before assigning to
! 	 * long doesn't do anything.
! 	 */
! 	bp->b_resid = (-addr->tmbc) & 0xffff;
  	ubadone(um);
  	iodone(bp);
  	/*
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet:	chris at umcp-cs		ARPA:	chris.umcp-cs at CSNet-Relay



More information about the Comp.unix.wizards mailing list