diff options
author | attilio <attilio@FreeBSD.org> | 2013-08-15 11:01:25 +0000 |
---|---|---|
committer | attilio <attilio@FreeBSD.org> | 2013-08-15 11:01:25 +0000 |
commit | ae49aeaba62c1f7009421f40d601061db0b3eefe (patch) | |
tree | 1e1dd3e40523f3eb8a564c2fad3920fe3917b97c /sys/vm | |
parent | b6945a92d66d759606a00571506ccf47e63d6961 (diff) | |
download | FreeBSD-src-ae49aeaba62c1f7009421f40d601061db0b3eefe.zip FreeBSD-src-ae49aeaba62c1f7009421f40d601061db0b3eefe.tar.gz |
On the recovery path for vm_page_alloc(), if a page had been requested
wired, unwind back the wiring bits otherwise we can end up freeing a
page that is considered wired.
Sponsored by: EMC / Isilon storage division
Reported by: alc
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/vm_page.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 0336e04..44a57fe 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -1611,6 +1611,10 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req) if (vp != NULL) vdrop(vp); pagedaemon_wakeup(); + if (req & VM_ALLOC_WIRED) { + atomic_subtract_int(&cnt.v_wire_count, 1); + m->wire_count = 0; + } m->object = NULL; vm_page_free(m); return (NULL); @@ -1806,8 +1810,13 @@ retry: &deferred_vdrop_list); if (vm_paging_needed()) pagedaemon_wakeup(); + if ((req & VM_ALLOC_WIRED) != 0) + atomic_subtract_int(&cnt.v_wire_count, + npages); for (m_tmp = m, m = m_ret; m < &m_ret[npages]; m++) { + if ((req & VM_ALLOC_WIRED) != 0) + m->wire_count = 0; if (m >= m_tmp) m->object = NULL; vm_page_free(m); |