Return to BSD News archive
Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!munnari.OZ.AU!news.ecn.uoknor.edu!news.wildstar.net!cancer.vividnet.com!hunter.premier.net!news.mathworks.com!fu-berlin.de!irz401!orion.sax.de!uriah.heep!news From: j@uriah.heep.sax.de (J Wunsch) Newsgroups: comp.unix.bsd.freebsd.misc Subject: Re: tar cMvf /dev/fd0 Date: 23 Oct 1996 19:11:54 GMT Organization: Private BSD site, Dresden Lines: 148 Message-ID: <54lqlq$q1p@uriah.heep.sax.de> References: <2h7mooa0i3.fsf@dslab7.cs.uit.no> <54989v$c8@uriah.heep.sax.de> <slrn56ks4p.3d7.hdm@dishmop.noc.demon.net> <54jl1j$k3o@uriah.heep.sax.de> Reply-To: joerg_wunsch@uriah.heep.sax.de (Joerg Wunsch) NNTP-Posting-Host: localhost.heep.sax.de Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-Newsreader: knews 0.9.6 X-Phone: +49-351-2012 669 X-PGP-Fingerprint: DC 47 E6 E4 FF A6 E9 8F 93 21 E0 7D F9 12 D6 4E I wrote: > Inherited bugs from the 386BSD floppy disk driver. > > I think the error is inside fdstrategy() about here: > > /* > * Set up block calculations. > */ > blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/fdblk; > nblocks = fd->ft->size; > if (blknum + (bp->b_bcount / fdblk) > nblocks) { > if (blknum == nblocks) { > bp->b_resid = bp->b_bcount; > } else { > bp->b_error = ENOSPC; > bp->b_flags |= B_ERROR; > } > goto bad; > } Unconfirmed and inofficial fix. Beat it, let me know if it still breaks. Index: fd.c =================================================================== RCS file: /home/ncvs/src/sys/i386/isa/fd.c,v retrieving revision 1.92 diff -u -u -r1.92 fd.c --- fd.c 1996/09/06 23:07:18 1.92 +++ fd.c 1996/10/23 18:39:28 @@ -84,7 +84,7 @@ #include <sys/devfsext.h> #endif -#define b_cylin b_resid /* XXX now spelled b_cylinder elsewhere */ +#define B_CYLINDER ((int)bp->b_driver1) /* misuse a flag to identify format operation */ #define B_FORMAT B_XXX @@ -1013,7 +1013,7 @@ void fdstrategy(struct buf *bp) { - long nblocks, blknum; + unsigned nblocks, blknum, cando; int s; fdcu_t fdcu; fdu_t fdu; @@ -1062,16 +1062,20 @@ */ blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/fdblk; nblocks = fd->ft->size; + bp->b_resid = 0; if (blknum + (bp->b_bcount / fdblk) > nblocks) { - if (blknum == nblocks) { - bp->b_resid = bp->b_bcount; + if (blknum <= nblocks) { + cando = (nblocks - blknum) * fdblk; + bp->b_resid = bp->b_bcount - cando; + if (cando == 0) + goto bad; /* not actually bad but EOF */ } else { - bp->b_error = ENOSPC; + bp->b_error = EINVAL; bp->b_flags |= B_ERROR; + goto bad; } - goto bad; } - bp->b_cylin = blknum / (fd->ft->sectrac * fd->ft->heads); + B_CYLINDER = (blknum / (fd->ft->sectrac * fd->ft->heads)); bp->b_pblkno = bp->b_blkno; s = splbio(); tqdisksort(&fdc->head, bp); @@ -1270,13 +1274,13 @@ fdc->state = DOSEEK; break; case DOSEEK: - if (bp->b_cylin == fd->track) + if (B_CYLINDER == fd->track) { fdc->state = SEEKCOMPLETE; break; } if (fd_cmd(fdcu, 3, NE7CMD_SEEK, - fd->fdsu, bp->b_cylin * fd->ft->steptrac, + fd->fdsu, B_CYLINDER * fd->ft->steptrac, 0)) { /* @@ -1298,7 +1302,7 @@ /* Make sure seek really happened*/ if(fd->track == FD_NO_TRACK) { - int descyl = bp->b_cylin * fd->ft->steptrac; + int descyl = B_CYLINDER * fd->ft->steptrac; do { /* * This might be a "ready changed" interrupt, @@ -1362,7 +1366,7 @@ } } - fd->track = bp->b_cylin; + fd->track = B_CYLINDER; if(format) fd->skip = (char *)&(finfo->fd_formb_cylno(0)) - (char *)finfo; @@ -1487,12 +1491,12 @@ } /* All OK */ fd->skip += fdblk; - if (!format && fd->skip < bp->b_bcount) + if (!format && fd->skip < bp->b_bcount - bp->b_resid) { /* set up next transfer */ blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/fdblk + fd->skip/fdblk; - bp->b_cylin = + B_CYLINDER = (blknum / (fd->ft->sectrac * fd->ft->heads)); fdc->state = DOSEEK; } @@ -1500,7 +1504,6 @@ { /* ALL DONE */ fd->skip = 0; - bp->b_resid = 0; TAILQ_REMOVE(&fdc->head, bp, b_act); biodone(bp); fdc->fd = (fd_p) 0; @@ -1654,7 +1657,7 @@ } bp->b_flags |= B_ERROR; bp->b_error = EIO; - bp->b_resid = bp->b_bcount - fdc->fd->skip; + bp->b_resid += bp->b_bcount - fdc->fd->skip; TAILQ_REMOVE(&fdc->head, bp, b_act); fdc->fd->skip = 0; biodone(bp); -- cheers, J"org joerg_wunsch@uriah.heep.sax.de -- http://www.sax.de/~joerg/ -- NIC: JW11-RIPE Never trust an operating system you don't have sources for. ;-)