From owner-freebsd-current Tue Sep 21 7:20:46 1999 Delivered-To: freebsd-current@freebsd.org Received: from mail2.fw-bc.sony.com (mail2.fw-bc.sony.com [198.83.177.13]) by hub.freebsd.org (Postfix) with ESMTP id 0BD9E15173 for ; Tue, 21 Sep 1999 07:20:41 -0700 (PDT) (envelope-from Internet.MailSystem@us-ti-xims-1.am.sony.com) Received: from mail1.bc.in.sel.sony.com (mail1.bc.in.sel.sony.com [43.144.65.11]) by mail2.fw-bc.sony.com (8.8.8/8.8.8) with ESMTP id OAA14103 for ; Tue, 21 Sep 1999 14:20:40 GMT Received: by mail1.bc.in.sel.sony.com id JAA26822; Tue, 21 Sep 1999 09:51:24 -0400 (EDT) Received: by us-ti-xims-1.am.sony.com with Internet Mail Service (5.5.2448.0) id ; Tue, 21 Sep 1999 09:51:23 -0400 Message-ID: <294F1168BAD0D21195680090271775CB451ECE@us-ti-xmsg-2.am.sony.com> From: Internet MailSystem To: current@FreeBSD.ORG Subject: request for review, patch to specfs to fix EOF condition alignmen t with buffer Date: Tue, 21 Sep 1999 09:51:22 -0400 MIME-Version: 1.0 X-Mailer: Internet Mail Service (5.5.2448.0) Content-Type: text/plain; charset="iso-2022-jp" Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG This is a request for a review. This patch fixes a bug in specfs relating to dealing with the EOF condition of a block device. If the EOF occurs in the middle of a block, specfs was not properly calculating the truncation for the I/O. This problem was first found by Tor. Tor's example creates an oddly-sized VN partition and then dd's from it. Without the patch the dd believes that it can read 2880 sectors. With the patch it correctly reads the last (truncated) block. dd if=/dev/zero of=/tmp/floppy.img bs=512 count=2879 vnconfig -s labels -c /dev/vn0 /tmp/floppy.img dd if=/dev/vn0 of=/dev/null bs=8k Once this patch is committed, the only problem we will have is in recognizing the write-EOF case, which I will have a recommendation for after this patch goes in. A similar problem in the VN device has already been fixed and committed. -Matt Index: miscfs/specfs/spec_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/specfs/spec_vnops.c,v retrieving revision 1.108 diff -u -r1.108 spec_vnops.c --- spec_vnops.c 1999/09/17 06:10:26 1.108 +++ spec_vnops.c 1999/09/20 17:50:48 @@ -311,19 +311,37 @@ do { bn = btodb(uio->uio_offset) & ~(bscale - 1); on = uio->uio_offset % bsize; - n = min((unsigned)(bsize - on), uio->uio_resid); if (seqcount > 1) { nextbn = bn + bscale; error = breadn(vp, bn, (int)bsize, &nextbn, (int *)&bsize, 1, NOCRED, &bp); } else { error = bread(vp, bn, (int)bsize, NOCRED, &bp); + } + + /* + * Figure out how much of the buffer is valid relative + * to our offset into the buffer, which may be negative + * if we are beyond the EOF. + * + * The valid size of the buffer is based on + * bp->b_bcount (which may have been truncated by + * dscheck or the device) minus bp->b_resid, which + * may be indicative of an I/O error if non-zero. + */ + n = bp->b_bcount - on; + if (n < 0) { + error = EINVAL; + } else { + n -= bp->b_resid; + if (n < 0) + error = EIO; } - n = min(n, bsize - bp->b_resid); if (error) { brelse(bp); return (error); } + n = min(n, uio->uio_resid); error = uiomove((char *)bp->b_data + on, n, uio); brelse(bp); } while (error == 0 && uio->uio_resid > 0 && n != 0); @@ -403,16 +421,48 @@ do { bn = btodb(uio->uio_offset) & ~blkmask; on = uio->uio_offset % bsize; + + /* + * Calculate potential request size, determine + * if we can avoid a read-before-write. + */ n = min((unsigned)(bsize - on), uio->uio_resid); if (n == bsize) bp = getblk(vp, bn, bsize, 0, 0); else error = bread(vp, bn, bsize, NOCRED, &bp); + + /* + * n is the amount of effective space in the buffer + * that we wish to write relative to our offset into + * the buffer. We have to truncate it to the valid + * size of the buffer relative to our offset into + * the buffer (which may end up being negative if + * we are beyond the EOF). + * + * The valid size of the buffer is based on + * bp->b_bcount (which may have been truncated by + * dscheck or the device) minus bp->b_resid, which + * may be indicative of an I/O error if non-zero. + * + * XXX In a newly created buffer, b_bcount == bsize + * and, being asynchronous, we have no idea of the + * EOF. + */ + if (error == 0) { + n = min(n, bp->b_bcount - on); + if (n < 0) { + error = EINVAL; + } else { + n -= bp->b_resid; + if (n < 0) + error = EIO; + } + } if (error) { brelse(bp); return (error); } - n = min(n, bsize - bp->b_resid); error = uiomove((char *)bp->b_data + on, n, uio); if (n + on == bsize) bawrite(bp); To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message