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