*BSD News Article 81468


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