svn commit: r239845 - stable/9/sys/fs/nfsclient
Konstantin Belousov
kib at FreeBSD.org
Wed Aug 29 15:50:10 UTC 2012
Author: kib
Date: Wed Aug 29 15:50:09 2012
New Revision: 239845
URL: http://svn.freebsd.org/changeset/base/239845
Log:
MFC r236687:
Improve handling of uiomove(9) errors for the NFS client.
Modified:
stable/9/sys/fs/nfsclient/nfs_clbio.c
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/fs/ (props changed)
Modified: stable/9/sys/fs/nfsclient/nfs_clbio.c
==============================================================================
--- stable/9/sys/fs/nfsclient/nfs_clbio.c Wed Aug 29 15:46:01 2012 (r239844)
+++ stable/9/sys/fs/nfsclient/nfs_clbio.c Wed Aug 29 15:50:09 2012 (r239845)
@@ -873,8 +873,9 @@ ncl_write(struct vop_write_args *ap)
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
daddr_t lbn;
int bcount;
- int n, on, error = 0;
- off_t tmp_off;
+ int bp_cached, n, on, error = 0;
+ size_t orig_resid, local_resid;
+ off_t orig_size, tmp_off;
KASSERT(uio->uio_rw == UIO_WRITE, ("ncl_write mode"));
KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
@@ -926,6 +927,11 @@ flush_and_restart:
mtx_unlock(&np->n_mtx);
}
+ orig_resid = uio->uio_resid;
+ mtx_lock(&np->n_mtx);
+ orig_size = np->n_size;
+ mtx_unlock(&np->n_mtx);
+
/*
* If IO_APPEND then load uio_offset. We restart here if we cannot
* get the append lock.
@@ -1103,7 +1109,10 @@ again:
* normally.
*/
+ bp_cached = 1;
if (on == 0 && n == bcount) {
+ if ((bp->b_flags & B_CACHE) == 0)
+ bp_cached = 0;
bp->b_flags |= B_CACHE;
bp->b_flags &= ~B_INVAL;
bp->b_ioflags &= ~BIO_ERROR;
@@ -1169,8 +1178,24 @@ again:
goto again;
}
+ local_resid = uio->uio_resid;
error = uiomove((char *)bp->b_data + on, n, uio);
+ if (error != 0 && !bp_cached) {
+ /*
+ * This block has no other content then what
+ * possibly was written by the faulty uiomove.
+ * Release it, forgetting the data pages, to
+ * prevent the leak of uninitialized data to
+ * usermode.
+ */
+ bp->b_ioflags |= BIO_ERROR;
+ brelse(bp);
+ uio->uio_offset -= local_resid - uio->uio_resid;
+ uio->uio_resid = local_resid;
+ break;
+ }
+
/*
* Since this block is being modified, it must be written
* again and not just committed. Since write clustering does
@@ -1179,17 +1204,18 @@ again:
*/
bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
- if (error) {
- bp->b_ioflags |= BIO_ERROR;
- brelse(bp);
- break;
- }
+ /*
+ * Get the partial update on the progress made from
+ * uiomove, if an error occured.
+ */
+ if (error != 0)
+ n = local_resid - uio->uio_resid;
/*
* Only update dirtyoff/dirtyend if not a degenerate
* condition.
*/
- if (n) {
+ if (n > 0) {
if (bp->b_dirtyend > 0) {
bp->b_dirtyoff = min(on, bp->b_dirtyoff);
bp->b_dirtyend = max((on + n), bp->b_dirtyend);
@@ -1218,8 +1244,22 @@ again:
} else {
bdwrite(bp);
}
+
+ if (error != 0)
+ break;
} while (uio->uio_resid > 0 && n > 0);
+ if (error != 0) {
+ if (ioflag & IO_UNIT) {
+ VATTR_NULL(&vattr);
+ vattr.va_size = orig_size;
+ /* IO_SYNC is handled implicitely */
+ (void)VOP_SETATTR(vp, &vattr, cred);
+ uio->uio_offset -= orig_resid - uio->uio_resid;
+ uio->uio_resid = orig_resid;
+ }
+ }
+
return (error);
}
More information about the svn-src-stable-9
mailing list