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. ;-)