aboutsummaryrefslogtreecommitdiff
path: root/sys/arm
diff options
context:
space:
mode:
authorAlan Cox <alc@FreeBSD.org>2007-11-17 22:52:29 +0000
committerAlan Cox <alc@FreeBSD.org>2007-11-17 22:52:29 +0000
commit59677d3c0ef101a2856b53c7aeccc1896eeeb064 (patch)
tree8c219244ed89f7561e53ea8b24266c64a0c5d008 /sys/arm
parent8d1e3aed2de0f1c8b2dc6800e5544bc7f1a72579 (diff)
downloadsrc-59677d3c0ef101a2856b53c7aeccc1896eeeb064.tar.gz
src-59677d3c0ef101a2856b53c7aeccc1896eeeb064.zip
Prevent the leakage of wired pages in the following circumstances:
First, a file is mmap(2)ed and then mlock(2)ed. Later, it is truncated. Under "normal" circumstances, i.e., when the file is not mlock(2)ed, the pages beyond the EOF are unmapped and freed. However, when the file is mlock(2)ed, the pages beyond the EOF are unmapped but not freed because they have a non-zero wire count. This can be a mistake. Specifically, it is a mistake if the sole reason why the pages are wired is because of wired, managed mappings. Previously, unmapping the pages destroys these wired, managed mappings, but does not reduce the pages' wire count. Consequently, when the file is unmapped, the pages are not unwired because the wired mapping has been destroyed. Moreover, when the vm object is finally destroyed, the pages are leaked because they are still wired. The fix is to reduce the pages' wired count by the number of wired, managed mappings destroyed. To do this, I introduce a new pmap function pmap_page_wired_mappings() that returns the number of managed mappings to the given physical page that are wired, and I use this function in vm_object_page_remove(). Reviewed by: tegge MFC after: 6 weeks
Notes
Notes: svn path=/head/; revision=173708
Diffstat (limited to 'sys/arm')
-rw-r--r--sys/arm/arm/pmap.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c
index 497846007eba..71d74291ad6e 100644
--- a/sys/arm/arm/pmap.c
+++ b/sys/arm/arm/pmap.c
@@ -4490,6 +4490,27 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
return (FALSE);
}
+/*
+ * pmap_page_wired_mappings:
+ *
+ * Return the number of managed mappings to the given physical page
+ * that are wired.
+ */
+int
+pmap_page_wired_mappings(vm_page_t m)
+{
+ pv_entry_t pv;
+ int count;
+
+ count = 0;
+ if ((m->flags & PG_FICTITIOUS) != 0)
+ return (count);
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list)
+ if ((pv->pv_flags & PVF_WIRED) != 0)
+ count++;
+ return (count);
+}
/*
* pmap_ts_referenced: