Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 8 Jul 2004 17:19:51 +1000 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        KOIE Hidetaka <koie@suri.co.jp>
Cc:        freebsd-gnats-submit@freebsd.org
Subject:   Re: kern/68690: write(2) returns wrong vlalue when EFAULT 
Message-ID:  <20040708170007.J706@gamplex.bde.org>
In-Reply-To: <20040708.120756.104051089.koie@suri.co.jp>
References:  <200407051221.i65CLC3Q057710@www.freebsd.org> <20040708.120756.104051089.koie@suri.co.jp>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 8 Jul 2004, KOIE Hidetaka wrote:

>   From:       Bruce Evans <bde@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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040708170007.J706>