--- sys/vm/device_pager.c.orig
+++ sys/vm/device_pager.c
@@ -213,7 +213,8 @@
 			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 @@
 	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 @@
 	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 @@
 		    (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)
--- sys/vm/vm_object.h.orig
+++ sys/vm/vm_object.h
@@ -134,7 +134,7 @@
 		 *	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;
--- sys/vm/vm_page.c.orig
+++ sys/vm/vm_page.c
@@ -1363,8 +1363,10 @@
 	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);
 }
 
--- tests/sys/vm/mmap_test.c.orig
+++ tests/sys/vm/mmap_test.c
@@ -362,6 +362,35 @@
 	ATF_REQUIRE(close(fd) == 0);
 }
 
+/* A regression test for a bug in the device pager. */
+ATF_TC_WITHOUT_HEAD(mmap__device_reinsert);
+ATF_TC_BODY(mmap__device_reinsert, tc)
+{
+	void *p;
+	int fd;
+
+	fd = open("/dev/devstat", O_RDONLY);
+	ATF_REQUIRE(fd >= 0);
+
+	p = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd, 0);
+	ATF_REQUIRE(p != MAP_FAILED);
+
+	/*
+	 * Use mlock() to trigger a fault, since msync() will not actually
+	 * remove the page from the process page tables.
+	 */
+	ATF_REQUIRE(mlock(p, getpagesize()) == 0);
+	ATF_REQUIRE(munlock(p, getpagesize()) == 0);
+	ATF_REQUIRE(msync(p, getpagesize(), MS_INVALIDATE) == 0);
+	ATF_REQUIRE(mlock(p, getpagesize()) == 0);
+	ATF_REQUIRE(munlock(p, getpagesize()) == 0);
+	ATF_REQUIRE(msync(p, getpagesize(), MS_INVALIDATE) == 0);
+	ATF_REQUIRE(mlock(p, getpagesize()) == 0);
+	ATF_REQUIRE(munlock(p, getpagesize()) == 0);
+
+	ATF_REQUIRE(munmap(p, getpagesize()) == 0);
+}
+
 ATF_TP_ADD_TCS(tp)
 {
 	ATF_TP_ADD_TC(tp, mmap__map_at_zero);
@@ -371,6 +400,7 @@
 	ATF_TP_ADD_TC(tp, mmap__write_only);
 	ATF_TP_ADD_TC(tp, mmap__maxprot_basic);
 	ATF_TP_ADD_TC(tp, mmap__maxprot_shm);
+	ATF_TP_ADD_TC(tp, mmap__device_reinsert);
 
 	return (atf_no_error());
 }
