diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1599,14 +1599,19 @@ /* * The page was left invalid. Likely placed there by * an incomplete fault. Just remove and ignore. + * + * However, if the map entry is wired, we must hang on to the + * page to avoid leaking it, since the entry owns the wiring(s). + * Invalid, wired pages can arise here if the backing pager is + * truncated. */ - if (vm_page_none_valid(m)) { + if (vm_page_none_valid(m) && entry->wired_count == 0) { if (vm_page_iter_remove(&pages, m)) vm_page_free(m); continue; } - /* vm_page_iter_rename() will dirty the page. */ + /* vm_page_iter_rename() will dirty the page if it is valid. */ if (!vm_page_iter_rename(&pages, m, new_object, m->pindex - offidxstart)) { vm_page_xunbusy(m); diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -2044,9 +2044,9 @@ * moving the page from object A to B, and will then later move * the backing store from A to B and we can't have a conflict. * - * Note: we *always* dirty the page. It is necessary both for the - * fact that we moved it, and because we may be invalidating - * swap. + * Note: callers will generally pass a valid page, in which case will we + * dirty it. This is necessary both for the fact that we moved it, + * and because we may be invalidating swap. * * The objects must be locked. */ @@ -2087,7 +2087,8 @@ m->object = new_object; vm_page_insert_radixdone(m, new_object, mpred); - vm_page_dirty(m); + if (vm_page_any_valid(m)) + vm_page_dirty(m); vm_pager_page_inserted(new_object, m); return (true); }