kern/68690: write(2) returns wrong vlalue when EFAULT

Bruce Evans bde at zeta.org.au
Thu Jul 8 00:20:28 PDT 2004


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

From: Bruce Evans <bde at zeta.org.au>
To: KOIE Hidetaka <koie at suri.co.jp>
Cc: freebsd-gnats-submit at freebsd.org, freebsd-bugs at freebsd.org
Subject: Re: kern/68690: write(2) returns wrong vlalue when EFAULT 
Date: Thu, 8 Jul 2004 17:19:51 +1000 (EST)

 On Thu, 8 Jul 2004, KOIE Hidetaka wrote:
 
 >   From:       Bruce Evans <bde at zeta.org.au>
 >   | Do you actually see the file pointer advanced?  This may be file system
 >   | dependent.  ffs is supposed to back out of the write, and it does so
 >   | for me.  Output:
 >   |
 >   | %%%
 >   | pos=0
 >   | write(20480)->-1 (should be 12288)
 >   | write: Bad address
 >   | pos=0 (should be 12288)
 >   | %%%
 >
 > I was unaware of examining on NFS.
 
 I think you mean that you saw this error for nfs.
 
 > %%%
 > pos=0
 > write(20480)->-1 (should be 12288)
 > write: Bad address
 > pos=8192 (should be 12288)
 > %%%
 >
 > The file pointer is not backed.
 
 I see this behaviour for nfs to.  It is because nfs_write() just doesn't
 back out of the write like ffs_write does.  From nfs_bio.c rev.1.132:
 
 % int
 % nfs_write(struct vop_write_args *ap)
 % {
 % ...
 % 	do {
 % ...
 % 		error = uiomove((char *)bp->b_data + on, n, uio);
 %
 % 		/*
 % 		 * Since this block is being modified, it must be written
 % 		 * again and not just committed.  Since write clustering does
 % 		 * not work for the stage 1 data write, only the stage 2
 % 		 * commit rpc, we have to clear B_CLUSTEROK as well.
 % 		 */
 % 		bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
 %
 % 		if (error) {
 % 			bp->b_ioflags |= BIO_ERROR;
 % 			brelse(bp);
 % 			break;
 % 		}
 % 	} while (uio->uio_resid > 0 && n > 0);
 %
 % 	if (haverslock)
 % 		nfs_rsunlock(np, td);
 %
 % 	return (error);
 % }
 
 After an error in uiomove(), nfs_write() just unlocks and returns, so
 it provides no protection from the bug in dofilewrite() even if the
 i/o was at the end of the file.  Only the case where the error occurs
 before any i/o is done is handled correctly.
 
 Bruce


More information about the freebsd-bugs mailing list