diff options
Diffstat (limited to 'sys/vm/vnode_pager.c')
-rw-r--r-- | sys/vm/vnode_pager.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 9e6363b..b0348c6 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -298,14 +298,18 @@ vnode_pager_setsize(vp, nsize) } /* * this gets rid of garbage at the end of a page that is now - * only partially backed by the vnode... + * only partially backed by the vnode. + * + * XXX for some reason (I don't know yet), if we take a + * completely invalid page and mark it partially valid + * it can screw up NFS reads, so we don't allow the case. */ if (nsize & PAGE_MASK) { vm_offset_t kva; vm_page_t m; m = vm_page_lookup(object, OFF_TO_IDX(nsize)); - if (m) { + if (m && m->valid) { int base = (int)nsize & PAGE_MASK; int size = PAGE_SIZE - base; @@ -318,6 +322,20 @@ vnode_pager_setsize(vp, nsize) vm_pager_unmap_page(kva); /* + * XXX work around SMP data integrity race + * by unmapping the page from user processes. + * The garbage we just cleared may be mapped + * to a user process running on another cpu + * and this code is not running through normal + * I/O channels which handle SMP issues for + * us, so unmap page to synchronize all cpus. + * + * XXX should vm_pager_unmap_page() have + * dealt with this? + */ + vm_page_protect(m, VM_PROT_NONE); + + /* * Clear out partial-page dirty bits. This * has the side effect of setting the valid * bits, but that is ok. There are a bunch @@ -325,6 +343,10 @@ vnode_pager_setsize(vp, nsize) * m->dirty == VM_PAGE_BITS_ALL. The file EOF * case is one of them. If the page is still * partially dirty, make it fully dirty. + * + * note that we do not clear out the valid + * bits. This would prevent bogus_page + * replacement from working properly. */ vm_page_set_validclean(m, base, size); if (m->dirty != 0) @@ -965,6 +987,9 @@ vnode_pager_generic_putpages(vp, m, bytecount, flags, rtvals) * may not properly clear the dirty bits for the entire page (which * could be VM_PAGE_BITS_ALL due to the page having been mmap()d). * With the page locked we are free to fix-up the dirty bits here. + * + * We do not under any circumstances truncate the valid bits, as + * this will screw up bogus page replacement. */ if (maxsize + poffset > object->un_pager.vnp.vnp_size) { if (object->un_pager.vnp.vnp_size > poffset) { |