summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordyson <dyson@FreeBSD.org>1996-10-17 03:04:43 +0000
committerdyson <dyson@FreeBSD.org>1996-10-17 03:04:43 +0000
commitb5f32c070137dc8420011863e90c869f511ace6e (patch)
tree0ba68fc0704de129f1718d26287bea91613946f1
parentea70b20311079a0f194091ef0c27458aabda1d30 (diff)
downloadFreeBSD-src-b5f32c070137dc8420011863e90c869f511ace6e.zip
FreeBSD-src-b5f32c070137dc8420011863e90c869f511ace6e.tar.gz
Fix a problem that could cause msync (or many other things) to deadlock.
The heuristic for managment of memory backing the buffer cache was nice, but didn't work due to some architectural problems. Simplify and improve the algorithm.
-rw-r--r--sys/kern/vfs_bio.c84
1 files changed, 40 insertions, 44 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index d65f2e7..f931f6d 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -18,7 +18,7 @@
* 5. Modifications may be freely made to this file if the above conditions
* are met.
*
- * $Id: vfs_bio.c,v 1.102 1996/09/20 02:26:35 dyson Exp $
+ * $Id: vfs_bio.c,v 1.103 1996/10/06 07:50:05 dyson Exp $
*/
/*
@@ -655,15 +655,15 @@ vfs_vmio_release(bp)
for (i = 0; i < bp->b_npages; i++) {
m = bp->b_pages[i];
bp->b_pages[i] = NULL;
- if ((bp->b_flags & B_ASYNC) == 0) {
- while ((m->flags & PG_BUSY) || (m->busy != 0)) {
- m->flags |= PG_WANTED;
- tsleep(m, PVM, "vmiorl", 0);
- }
- }
-
vm_page_unwire(m);
-
+ /*
+ * We don't mess with busy pages, it is
+ * the responsibility of the process that
+ * busied the pages to deal with them.
+ */
+ if ((m->flags & PG_BUSY) || (m->busy != 0))
+ continue;
+
if (m->wire_count == 0) {
if (m->flags & PG_WANTED) {
@@ -671,47 +671,43 @@ vfs_vmio_release(bp)
wakeup(m);
}
- if (bp->b_flags & B_ASYNC) {
- if (m->hold_count == 0) {
- if ((m->flags & PG_BUSY) == 0 &&
- (m->busy == 0) &&
- (m->valid == 0)) {
- if(m->dirty == 0)
- vm_page_test_dirty(m);
- if (m->dirty == 0) {
- vm_page_protect(m, VM_PROT_NONE);
- vm_page_free(m);
- } else {
- pagedaemon_wakeup();
- }
+ /*
+ * If this is an async free -- we cannot place
+ * pages onto the cache queue, so our policy for
+ * such buffers is to avoid the cache queue, and
+ * only modify the active queue or free queue.
+ */
+ if ((bp->b_flags & B_ASYNC) == 0) {
+
+ /*
+ * In the case of sync buffer frees, we can do pretty much
+ * anything to any of the memory queues. Specifically,
+ * the cache queue is free to be modified.
+ */
+ if (m->valid) {
+ if(m->dirty == 0)
+ vm_page_test_dirty(m);
/*
- * This is likely at interrupt time,
- * and we cannot block here.
+ * this keeps pressure off of the process memory
*/
- } else if (cnt.v_free_count < cnt.v_free_min) {
- pagedaemon_wakeup();
+ if ((vm_swap_size == 0) ||
+ (cnt.v_free_count < cnt.v_free_min)) {
+ if ((m->dirty == 0) &&
+ (m->hold_count == 0))
+ vm_page_cache(m);
+ else
+ vm_page_deactivate(m);
}
+ } else if (m->hold_count == 0) {
+ vm_page_protect(m, VM_PROT_NONE);
+ vm_page_free(m);
}
- continue;
- }
-
- if (m->valid) {
- if(m->dirty == 0)
- vm_page_test_dirty(m);
+ } else {
/*
- * this keeps pressure off of the process memory
+ * If async, then at least we clear the
+ * act_count.
*/
- if ((vm_swap_size == 0) ||
- (cnt.v_free_count < cnt.v_free_min)) {
- if ((m->dirty == 0) &&
- (m->hold_count == 0))
- vm_page_cache(m);
- else
- vm_page_deactivate(m);
- }
- } else if (m->hold_count == 0) {
- vm_page_protect(m, VM_PROT_NONE);
- vm_page_free(m);
+ m->act_count = 0;
}
}
}
OpenPOWER on IntegriCloud