Date: Mon, 11 Feb 2002 22:41:45 +1100 (EST) From: Bruce Evans <bde@zeta.org.au> To: Matteo <drummino@yahoo.com> Cc: <freebsd-stable@FreeBSD.ORG>, <freebsd-bugs@FreeBSD.ORG>, <aiuto@gufi.org>, <dillon@FreeBSD.ORG> Subject: Re: Crash System with MSDOS file-system driver! Message-ID: <20020211221141.R682-100000@gamplex.bde.org> In-Reply-To: <20020208163715.14085.qmail@web13205.mail.yahoo.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, 8 Feb 2002, Matteo wrote: > Hi all, > > I've 4.5-RELEASE and 4.4-STABLE. > > Try to follow this steps: > > 1) Mount a msdos floppy write protected in /floppy > 2) cd /floppy > 3) rm somefile > At this point kernel show this message: > > fd0c: hard error writing fsbn 56 of 56-63 (ST0 > 40<abnrml> ST1 2<write_prosend out a error messages... > etc etc > > Next Step: > > 4) ls > > And system halt! I try with a UFS floppy and it's all > ok. %%% The hang is caused by msdosfs_readdir() "handling" reads of 0 bytes by spinning forever. msdosfs_read() seems to have the same bug. ufs_readdir() works because it calls VOP_READ() == ffs_read() which treats reads of 0 bytes as EOF instead of spinning forever. Reads of 0 bytes and other short reads shouldn't happen, but they happen because failed writes clobber b_resid and breadn() later returns with the clobbered value. Filesystems use b_resid to determine the extent of i/o in a few places (all (?) cloned from ufs_readwrite.c). This is probably wrong and very incomplete -- most places, including critical block allocation code, just assume that breadn() returns an error if everything could not be read. The patch mainly just resets b_resid in breadn(). Determining the value after the i/o that filled the buffer doesn't seem to be easy, but it should be 0. Index: vfs_bio.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_bio.c,v retrieving revision 1.296 diff -u -r1.296 vfs_bio.c --- vfs_bio.c 31 Jan 2002 18:39:44 -0000 1.296 +++ vfs_bio.c 11 Feb 2002 11:09:22 -0000 @@ -614,6 +614,13 @@ vfs_busy_pages(bp, 0); VOP_STRATEGY(vp, bp); ++readwait; + } else { + /* + * Recover from failed writes clobbering b_resid. b_resid is + * strictly only valid after i/o, but some filesystems expect + * it to give the part of `size' that was not readable here. + */ + bp->b_resid = 0; } for (i = 0; i < cnt; i++, rablkno++, rabsize++) { @@ -640,6 +647,16 @@ if (readwait) { rv = bufwait(bp); + /* + * Convert short reads to i/o errors, since short reads aren't + * useful for the buffer cache and they are mostly not handled + * in callers. + * XXX we don't always get here for read-ahead blocks. + * b_resid for read-ahead blocks may be clobbered by failed + * attempts to write the blocks. + */ + if (rv == 0 && bp->b_resid != 0) + rv = EIO; } return (rv); } %%% Bruce To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-stable" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020211221141.R682-100000>