summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authortegge <tegge@FreeBSD.org>2002-02-19 23:19:30 +0000
committertegge <tegge@FreeBSD.org>2002-02-19 23:19:30 +0000
commit5f4060fe3b8fa452dbd71d3403ece380470dae76 (patch)
tree99edeec5e5d906e1fc6a786d33ae94e0a71f13df /sys
parent872134cfe5d102e39b3dbc8363c48462882de702 (diff)
downloadFreeBSD-src-5f4060fe3b8fa452dbd71d3403ece380470dae76.zip
FreeBSD-src-5f4060fe3b8fa452dbd71d3403ece380470dae76.tar.gz
Add a page queue, PQ_HOLD, that temporarily owns pages with nonzero hold
count that would otherwise be on one of the free queues. This eliminates a panic when broken programs unmap memory that still has pending IO from raw devices. Reviewed by: dillon, alc
Diffstat (limited to 'sys')
-rw-r--r--sys/vm/vm_page.c11
-rw-r--r--sys/vm/vm_page.h3
-rw-r--r--sys/vm/vm_pageq.c1
3 files changed, 11 insertions, 4 deletions
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 047125f..5141708 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -413,6 +413,8 @@ vm_page_unhold(vm_page_t mem)
GIANT_REQUIRED;
--mem->hold_count;
KASSERT(mem->hold_count >= 0, ("vm_page_unhold: hold count < 0!!!"));
+ if (mem->hold_count == 0 && mem->queue == PQ_HOLD)
+ vm_page_free_toq(mem);
}
/*
@@ -1108,8 +1110,7 @@ vm_page_free_toq(vm_page_t m)
s = splvm();
cnt.v_tfree++;
- if (m->busy || ((m->queue - m->pc) == PQ_FREE) ||
- (m->hold_count != 0)) {
+ if (m->busy || ((m->queue - m->pc) == PQ_FREE)) {
printf(
"vm_page_free: pindex(%lu), busy(%d), PG_BUSY(%d), hold(%d)\n",
(u_long)m->pindex, m->busy, (m->flags & PG_BUSY) ? 1 : 0,
@@ -1178,7 +1179,11 @@ vm_page_free_toq(vm_page_t m)
#endif
}
- m->queue = PQ_FREE + m->pc;
+ if (m->hold_count != 0) {
+ m->flags &= ~PG_ZERO;
+ m->queue = PQ_HOLD;
+ } else
+ m->queue = PQ_FREE + m->pc;
pq = &vm_page_queues[m->queue];
pq->lcnt++;
++(*pq->cnt);
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index a2e67df..3610ae0 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -215,7 +215,8 @@ struct vm_page {
#define PQ_INACTIVE (1 + 1*PQ_L2_SIZE)
#define PQ_ACTIVE (2 + 1*PQ_L2_SIZE)
#define PQ_CACHE (3 + 1*PQ_L2_SIZE)
-#define PQ_COUNT (3 + 2*PQ_L2_SIZE)
+#define PQ_HOLD (3 + 2*PQ_L2_SIZE)
+#define PQ_COUNT (4 + 2*PQ_L2_SIZE)
#else
#define PQ_NONE PQ_COUNT
#define PQ_FREE 0
diff --git a/sys/vm/vm_pageq.c b/sys/vm/vm_pageq.c
index b0b050b..2e47538 100644
--- a/sys/vm/vm_pageq.c
+++ b/sys/vm/vm_pageq.c
@@ -39,6 +39,7 @@ vm_pageq_init(void)
}
vm_page_queues[PQ_INACTIVE].cnt = &cnt.v_inactive_count;
vm_page_queues[PQ_ACTIVE].cnt = &cnt.v_active_count;
+ vm_page_queues[PQ_HOLD].cnt = &cnt.v_active_count;
for (i = 0; i < PQ_COUNT; i++) {
TAILQ_INIT(&vm_page_queues[i].pl);
OpenPOWER on IntegriCloud