From owner-freebsd-bugs@FreeBSD.ORG Sat May 17 02:20:13 2003 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 9849937B404 for ; Sat, 17 May 2003 02:20:13 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id E90B143F93 for ; Sat, 17 May 2003 02:20:12 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.9/8.12.9) with ESMTP id h4H9KCUp066379 for ; Sat, 17 May 2003 02:20:12 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.9/8.12.9/Submit) id h4H9KBEW066377; Sat, 17 May 2003 02:20:11 -0700 (PDT) Date: Sat, 17 May 2003 02:20:11 -0700 (PDT) Message-Id: <200305170920.h4H9KBEW066377@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: Yar Tikhiy Subject: Re: kern/52338: fd(4) floppy disk driver & non-blocking I/O X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Yar Tikhiy List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 17 May 2003 09:20:14 -0000 The following reply was made to PR kern/52338; it has been noted by GNATS. From: Yar Tikhiy To: Bruce Evans Cc: FreeBSD-gnats-submit@freebsd.org, freebsd-bugs@freebsd.org, joerg@freebsd.org Subject: Re: kern/52338: fd(4) floppy disk driver & non-blocking I/O Date: Sat, 17 May 2003 13:10:47 +0400 [I'm adding joerg@, who has hacked fdc(4) a lot, to CC: ] [so he can participate in this discussion. ] I'm testing a somewhat different patch: ============================================================================== --- fd.c.orig Fri Apr 11 15:39:24 2003 +++ fd.c Sat May 17 13:05:32 2003 @@ -1667,11 +1667,16 @@ panic("fdstrategy: buf for nonexistent device (%#lx, %#lx)", (u_long)major(bp->bio_dev), (u_long)minor(bp->bio_dev)); fdc = fd->fdc; - if (fd->type == FDT_NONE || fd->ft == 0) { + if (fd->type == FDT_NONE) { bp->bio_error = ENXIO; bp->bio_flags |= BIO_ERROR; goto bad; } + if (fd->ft == 0) { + bp->bio_error = EAGAIN; + bp->bio_flags |= BIO_ERROR; + goto bad; + } fdblk = 128 << (fd->ft->secsize); if (bp->bio_cmd != FDBIO_FORMAT && bp->bio_cmd != FDBIO_RDSECTID) { if (fd->flags & FD_NONBLOCK) { @@ -2605,6 +2610,7 @@ { fdu_t fdu; fd_p fd; + struct fd_type *ft; struct fdc_status *fsp; struct fdc_readid *rid; size_t fdblk; @@ -2614,6 +2620,14 @@ type = FDTYPE(minor(dev)); fd = devclass_get_softc(fd_devclass, fdu); + if (fd->type == FDT_NONE) + return (ENXIO); + if (fd->ft == 0) + /* no type known yet, use the native type */ + ft = &fd_native_types[fd->type]; + else + ft = fd->ft; + /* * First, handle everything that could be done with * FD_NONBLOCK still being set. @@ -2621,11 +2635,11 @@ switch (cmd) { case DIOCGMEDIASIZE: - *(off_t *)addr = (128 << (fd->ft->secsize)) * fd->ft->size; + *(off_t *)addr = (128 << (ft->secsize)) * ft->size; return (0); case DIOCGSECTORSIZE: - *(u_int *)addr = 128 << (fd->ft->secsize); + *(u_int *)addr = 128 << (ft->secsize); return (0); case FIONBIO: @@ -2648,11 +2662,7 @@ return (0); case FD_GTYPE: /* get drive type */ - if (fd->ft == 0) - /* no type known yet, return the native type */ - *(struct fd_type *)addr = fd_native_types[fd->type]; - else - *(struct fd_type *)addr = *fd->ft; + *(struct fd_type *)addr = *ft; return (0); case FD_STYPE: /* set drive type */ ============================================================================== It is intended to achieve two goals: - first, to change the buffer error status in fdstrategy() for the fd->ft==NULL case, so read(2) or write(2) will return EAGAIN, as per the fdc(4) manpage; - second, to make fdioctl() return geometry defaults for the current fd->type if fd->ft is NULL. Its second part works well, though I'm unsure which way is better, mine (use a default fd_type) or yours (return ENXIO). But its first part yields an unexpected result: No error from read() is reported at all! That happens because fdstrategy() doesn't set bp->b_resid when indicating a error on a buffer; consequently, the corresponding uio structure gets indication in physio() that the data has been transferred; and dofileread() will clear the error status if any bytes have been transferred and the error status is EAGAIN or EINTR (see kern/sys_generic.c at line 195). I must admit that my current knowledge of BIO is insufficient to understand what is actually wrong with the above scheme. Any idea? -- Yar