summaryrefslogtreecommitdiffstats
path: root/sys/nfsclient
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>1999-04-05 19:38:30 +0000
committerjulian <julian@FreeBSD.org>1999-04-05 19:38:30 +0000
commit0ed09d2ad576c0a64797f8ca9bebd32873f770ae (patch)
tree6de1ee6b7f198b11b20d471fbc1a36de8329d82e /sys/nfsclient
parent9ac433dd352fdfe7f3038aa0e1a4333686bc07fc (diff)
downloadFreeBSD-src-0ed09d2ad576c0a64797f8ca9bebd32873f770ae.zip
FreeBSD-src-0ed09d2ad576c0a64797f8ca9bebd32873f770ae.tar.gz
Catch a case spotted by Tor where files mmapped could leave garbage in the
unallocated parts of the last page when the file ended on a frag but not a page boundary. Delimitted by tags PRE_MATT_MMAP_EOF and POST_MATT_MMAP_EOF, in files alpha/alpha/pmap.c i386/i386/pmap.c nfs/nfs_bio.c vm/pmap.h vm/vm_page.c vm/vm_page.h vm/vnode_pager.c miscfs/specfs/spec_vnops.c ufs/ufs/ufs_readwrite.c kern/vfs_bio.c Submitted by: Matt Dillon <dillon@freebsd.org> Reviewed by: Alan Cox <alc@freebsd.org>
Diffstat (limited to 'sys/nfsclient')
-rw-r--r--sys/nfsclient/nfs_bio.c56
1 files changed, 46 insertions, 10 deletions
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
index 2fb5353..1d573ea 100644
--- a/sys/nfsclient/nfs_bio.c
+++ b/sys/nfsclient/nfs_bio.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
- * $Id: nfs_bio.c,v 1.66 1999/01/21 08:29:07 dillon Exp $
+ * $Id: nfs_bio.c,v 1.67 1999/03/12 02:24:58 julian Exp $
*/
@@ -144,6 +144,12 @@ nfs_getpages(ap)
return VM_PAGER_ERROR;
}
+ /*
+ * Calculate the number of bytes read and validate only that number
+ * of bytes. Note that due to pending writes, size may be 0. This
+ * does not mean that the remaining data is invalid!
+ */
+
size = count - uio.uio_resid;
for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
@@ -154,11 +160,19 @@ nfs_getpages(ap)
m->flags &= ~PG_ZERO;
if (nextoff <= size) {
+ /*
+ * Read operation filled an entire page
+ */
m->valid = VM_PAGE_BITS_ALL;
m->dirty = 0;
- } else {
- int nvalid = ((size + DEV_BSIZE - 1) - toff) & ~(DEV_BSIZE - 1);
- vm_page_set_validclean(m, 0, nvalid);
+ } else if (size > toff) {
+ /*
+ * Read operation filled a partial page, set valid
+ * bits properly. validclean will zero out
+ * any cruft in the buffer when setting a valid bit,
+ * if the size is not DEV_BSIZE aligned.
+ */
+ vm_page_set_validclean(m, 0, size - toff);
}
if (i != ap->a_reqpage) {
@@ -183,6 +197,13 @@ nfs_getpages(ap)
} else {
vnode_pager_freepage(m);
}
+ } else {
+ /*
+ * This page is being mapped, clear out any other
+ * cruft in the invalid areas of the page.
+ */
+ if (m->valid && m->valid != VM_PAGE_BITS_ALL)
+ vm_page_zero_invalid(m, FALSE);
}
}
return 0;
@@ -784,8 +805,16 @@ again:
}
np->n_flag |= NMODIFIED;
+ /*
+ * If dirtyend exceeds file size, chop it down. If this
+ * creates a reverse-indexed or degenerate situation with
+ * dirtyoff/end, 0 them.
+ */
+
if ((off_t)bp->b_blkno * DEV_BSIZE + bp->b_dirtyend > np->n_size)
bp->b_dirtyend = np->n_size - (off_t)bp->b_blkno * DEV_BSIZE;
+ if (bp->b_dirtyoff >= bp->b_dirtyend)
+ bp->b_dirtyoff = bp->b_dirtyend = 0;
/*
* If the new write will leave a contiguous dirty
@@ -838,13 +867,20 @@ again:
*/
nfs_prot_buf(bp, on, n);
- if (bp->b_dirtyend > 0) {
- bp->b_dirtyoff = min(on, bp->b_dirtyoff);
- bp->b_dirtyend = max((on + n), bp->b_dirtyend);
- } else {
- bp->b_dirtyoff = on;
- bp->b_dirtyend = on + n;
+ /*
+ * Only update dirtyoff/dirtyend if not a degenerate
+ * condition.
+ */
+ if (n) {
+ if (bp->b_dirtyend > 0) {
+ bp->b_dirtyoff = min(on, bp->b_dirtyoff);
+ bp->b_dirtyend = max((on + n), bp->b_dirtyend);
+ } else {
+ bp->b_dirtyoff = on;
+ bp->b_dirtyend = on + n;
+ }
}
+
/*
* To avoid code complexity, we may have to throw away
* previously valid ranges when merging the new dirty range
OpenPOWER on IntegriCloud