Don't decref page map pages
I triggered this due to another bug. Basically, map_page_at_addr()'s two
error-cases assumed the page was not in the page map. Those pages
shouldn't be decreffed; the page map manages their refcnt.
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
diff --git a/kern/src/mm.c b/kern/src/mm.c
index 0890591..80c0d7e 100644
--- a/kern/src/mm.c
+++ b/kern/src/mm.c
@@ -357,6 +357,7 @@
{
int ret = 0;
struct vm_region *vmr, *vm_i;
+
TAILQ_FOREACH(vm_i, &p->vm_regions, vm_link) {
vmr = kmem_cache_alloc(vmr_kcache, 0);
if (!vmr)
@@ -391,6 +392,12 @@
int count = 0;
struct vm_region *vmr;
printk("VM Regions for proc %d\n", p->pid);
+ printk("NR:"
+ " Range:"
+ " Prot,"
+ " Flags,"
+ " File,"
+ " Off\n");
TAILQ_FOREACH(vmr, &p->vm_regions, vm_link)
printk("%02d: (%p - %p): 0x%08x, 0x%08x, %p, %p\n", count++,
vmr->vm_base, vmr->vm_end, vmr->vm_prot, vmr->vm_flags,
@@ -529,8 +536,9 @@
* in which case we should just return. */
if (pte_is_present(pte)) {
spin_unlock(&p->pte_lock);
- /* callers expect us to eat the ref if we succeed. */
- page_decref(page);
+ /* non-PM callers expect us to eat the ref if we succeed. */
+ if (!page_is_pagemap(page))
+ page_decref(page);
return 0;
}
if (pte_is_mapped(pte)) {
@@ -540,7 +548,8 @@
warn_once("Clobbered a PTE mapping (%p -> %p)\n", pte_print(pte),
page2pa(page) | prot);
}
- page_decref(pa2page(pte_get_paddr(pte)));
+ if (!page_is_pagemap(pa2page(pte_get_paddr(pte))))
+ page_decref(pa2page(pte_get_paddr(pte)));
}
/* preserve the dirty bit - pm removal could be looking concurrently */
prot |= (pte_is_dirty(pte) ? PTE_D : 0);