diff options
author | tegge <tegge@FreeBSD.org> | 2002-02-19 23:19:30 +0000 |
---|---|---|
committer | tegge <tegge@FreeBSD.org> | 2002-02-19 23:19:30 +0000 |
commit | 5f4060fe3b8fa452dbd71d3403ece380470dae76 (patch) | |
tree | 99edeec5e5d906e1fc6a786d33ae94e0a71f13df /sys/vm/vm_page.c | |
parent | 872134cfe5d102e39b3dbc8363c48462882de702 (diff) | |
download | FreeBSD-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/vm/vm_page.c')
-rw-r--r-- | sys/vm/vm_page.c | 11 |
1 files changed, 8 insertions, 3 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); |