From 1b26eb10ffa2a67cdcae285e359256bac193319f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 19 Oct 2003 00:01:56 +0000 Subject: [PATCH] - Synchronize access to a vm page's valid field using the containing vm object's lock. - Reduce the scope of the vm page queues lock in two places. --- sys/vm/vnode_pager.c | 86 ++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 70b898777cb2..5faad5c88260 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -324,49 +324,48 @@ vnode_pager_setsize(vp, nsize) * it can screw up NFS reads, so we don't allow the case. */ if ((nsize & PAGE_MASK) && - (m = vm_page_lookup(object, OFF_TO_IDX(nsize))) != NULL) { + (m = vm_page_lookup(object, OFF_TO_IDX(nsize))) != NULL && + m->valid != 0) { + int base = (int)nsize & PAGE_MASK; + int size = PAGE_SIZE - base; + + /* + * Clear out partial-page garbage in case + * the page has been mapped. + */ + pmap_zero_page_area(m, base, size); + + /* + * 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_lock_queues(); - if (m->valid) { - int base = (int)nsize & PAGE_MASK; - int size = PAGE_SIZE - base; + pmap_remove_all(m); - /* - * Clear out partial-page garbage in case - * the page has been mapped. - */ - pmap_zero_page_area(m, base, size); - - /* - * 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? - */ - pmap_remove_all(m); - - /* - * Clear out partial-page dirty bits. This - * has the side effect of setting the valid - * bits, but that is ok. There are a bunch - * of places in the VM system where we expected - * 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) - m->dirty = VM_PAGE_BITS_ALL; - } + /* + * Clear out partial-page dirty bits. This + * has the side effect of setting the valid + * bits, but that is ok. There are a bunch + * of places in the VM system where we expected + * 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) + m->dirty = VM_PAGE_BITS_ALL; vm_page_unlock_queues(); } } @@ -573,14 +572,17 @@ vnode_pager_input_old(object, m) bzero((caddr_t) kva + count, PAGE_SIZE - count); } vm_pager_unmap_page(kva); + + VM_OBJECT_LOCK(object); } vm_page_lock_queues(); pmap_clear_modify(m); vm_page_undirty(m); vm_page_flag_clear(m, PG_ZERO); + vm_page_unlock_queues(); if (!error) m->valid = VM_PAGE_BITS_ALL; - vm_page_unlock_queues(); + VM_OBJECT_UNLOCK(object); return error ? VM_PAGER_ERROR : VM_PAGER_OK; }