kern/52338: fd(4) floppy disk driver & non-blocking I/O

Yar Tikhiy yar at comp.chem.msu.su
Sat May 17 02:20:14 PDT 2003


The following reply was made to PR kern/52338; it has been noted by GNATS.

From: Yar Tikhiy <yar at comp.chem.msu.su>
To: Bruce Evans <bde at zeta.org.au>
Cc: FreeBSD-gnats-submit at freebsd.org, freebsd-bugs at freebsd.org,
	joerg at 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


More information about the freebsd-bugs mailing list