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

Bruce Evans bde at zeta.org.au
Thu Jul 8 00:19:56 PDT 2004


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