summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2003-10-19 00:01:56 +0000
committeralc <alc@FreeBSD.org>2003-10-19 00:01:56 +0000
commitcc2c1485cf2e7e4c46e59477a5e2a765b2af80b1 (patch)
tree23d0f11d994d49865d9a963521e989558a631bf0 /sys
parent509f7279a89d6cf2be7afad8462f16b4fd2579fb (diff)
downloadFreeBSD-src-cc2c1485cf2e7e4c46e59477a5e2a765b2af80b1.zip
FreeBSD-src-cc2c1485cf2e7e4c46e59477a5e2a765b2af80b1.tar.gz
- 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.
Diffstat (limited to 'sys')
-rw-r--r--sys/vm/vnode_pager.c88
1 files changed, 45 insertions, 43 deletions
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 70b8987..5faad5c 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;
-
- /*
- * 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;
- }
+ 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;
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;
}
OpenPOWER on IntegriCloud