summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2004-02-10 18:34:27 +0000
committeralc <alc@FreeBSD.org>2004-02-10 18:34:27 +0000
commit4a9de29e2400323b6fac0d021a51103b14424fa4 (patch)
tree925208e1537c73c5e3af9132ee366b748e8ec29c /sys
parent82f2a8ccb0aa16d4b82e71a75b2c3ce15f7a82a2 (diff)
downloadFreeBSD-src-4a9de29e2400323b6fac0d021a51103b14424fa4.zip
FreeBSD-src-4a9de29e2400323b6fac0d021a51103b14424fa4.tar.gz
Correct a long-standing race condition in the inactive queue scan. (See
the added comment for low-level details.) The effect of this race condition is a panic "vm_page_cache: caching a dirty page, ..." Reviewed by: tegge MFC after: 7 days
Diffstat (limited to 'sys')
-rw-r--r--sys/vm/vm_pageout.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 506f1ec..f807b77 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -803,6 +803,21 @@ rescan0:
*/
if (m->dirty == 0) {
vm_page_test_dirty(m);
+ /*
+ * Avoid a race condition: Unless write access is
+ * removed from the page, another processor could
+ * modify it before all access is removed by the call
+ * to vm_page_cache() below. If vm_page_cache() finds
+ * that the page has been modified when it removes all
+ * access, it panics because it cannot cache dirty
+ * pages. In principle, we could eliminate just write
+ * access here rather than all access. In the expected
+ * case, when there are no last instant modifications
+ * to the page, removing all access will be cheaper
+ * overall.
+ */
+ if (m->dirty == 0 && (m->flags & PG_WRITEABLE) != 0)
+ pmap_remove_all(m);
} else {
vm_page_dirty(m);
}
OpenPOWER on IntegriCloud