aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/vm/device_pager.c36
-rw-r--r--sys/vm/vm_object.h2
-rw-r--r--sys/vm/vm_page.c6
3 files changed, 25 insertions, 19 deletions
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c
index 221969307ba4..9277d6255418 100644
--- a/sys/vm/device_pager.c
+++ b/sys/vm/device_pager.c
@@ -213,7 +213,8 @@ again:
object1 = NULL;
object->handle = handle;
object->un_pager.devp.ops = ops;
- TAILQ_INIT(&object->un_pager.devp.devp_pglist);
+ if (object->type == OBJT_DEVICE)
+ vm_object_set_flag(object, OBJ_PG_DTOR);
TAILQ_INSERT_TAIL(&dev_pager_object_list, object,
pager_object_list);
mtx_unlock(&dev_pager_mtx);
@@ -325,15 +326,12 @@ dev_pager_free_page(vm_object_t object, vm_page_t m)
KASSERT((object->type == OBJT_DEVICE &&
(m->oflags & VPO_UNMANAGED) != 0),
("Managed device or page obj %p m %p", object, m));
- TAILQ_REMOVE(&object->un_pager.devp.devp_pglist, m, plinks.q);
vm_page_putfake(m);
}
static void
dev_pager_dealloc(vm_object_t object)
{
- vm_page_t m;
-
VM_OBJECT_WUNLOCK(object);
object->un_pager.devp.ops->cdev_pg_dtor(object->un_pager.devp.handle);
@@ -343,15 +341,25 @@ dev_pager_dealloc(vm_object_t object)
VM_OBJECT_WLOCK(object);
if (object->type == OBJT_DEVICE) {
- /*
- * Free up our fake pages.
- */
- while ((m = TAILQ_FIRST(&object->un_pager.devp.devp_pglist))
- != NULL) {
- if (vm_page_busy_acquire(m, VM_ALLOC_WAITFAIL) == 0)
- continue;
+ struct pctrie_iter pages;
+ vm_page_t m;
- dev_pager_free_page(object, m);
+ vm_page_iter_init(&pages, object);
+restart:
+ VM_RADIX_FOREACH(m, &pages) {
+ if (!vm_page_busy_acquire(m, VM_ALLOC_WAITFAIL)) {
+ pctrie_iter_reset(&pages);
+ goto restart;
+ }
+ if (vm_page_iter_remove(&pages, m)) {
+ /*
+ * We could end up with invalid pages installed
+ * by the generic page fault handler. Typically
+ * these are replaced by the device pager.
+ */
+ vm_page_free(m);
+ } else if ((m->flags & PG_FICTITIOUS) != 0)
+ dev_pager_free_page(object, m);
}
}
object->handle = NULL;
@@ -380,10 +388,6 @@ dev_pager_getpages(vm_object_t object, vm_page_t *ma, int count, int *rbehind,
(object->type == OBJT_MGTDEVICE &&
(ma[0]->oflags & VPO_UNMANAGED) == 0),
("Wrong page type %p %p", ma[0], object));
- if (object->type == OBJT_DEVICE) {
- TAILQ_INSERT_TAIL(&object->un_pager.devp.devp_pglist,
- ma[0], plinks.q);
- }
if (rbehind)
*rbehind = 0;
if (rahead)
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
index b056ebe9a4b7..694b9d77a12d 100644
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -134,7 +134,7 @@ struct vm_object {
* devp_pglist - list of allocated pages
*/
struct {
- TAILQ_HEAD(, vm_page) devp_pglist;
+ void *spare[2];
const struct cdev_pager_ops *ops;
void *handle;
} devp;
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index b39d665f9e0f..3753079f2fde 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -1363,8 +1363,10 @@ vm_page_putfake(vm_page_t m)
KASSERT((m->oflags & VPO_UNMANAGED) != 0, ("managed %p", m));
KASSERT((m->flags & PG_FICTITIOUS) != 0,
("vm_page_putfake: bad page %p", m));
- vm_page_assert_xbusied(m);
- vm_page_busy_free(m);
+ if (m->object != NULL) {
+ vm_page_assert_xbusied(m);
+ vm_page_busy_free(m);
+ }
uma_zfree(fakepg_zone, m);
}