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 | |
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')
-rw-r--r-- | sys/vm/vm_page.c | 11 | ||||
-rw-r--r-- | sys/vm/vm_page.h | 3 | ||||
-rw-r--r-- | sys/vm/vm_pageq.c | 1 |
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); |