diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -1743,6 +1743,52 @@ (vm_size_t)(prev_entry->end - prev_entry->start), (vm_size_t)(end - prev_entry->end), cred != NULL && (protoeflags & MAP_ENTRY_NEEDS_COPY) == 0)) { +#ifdef INVARIANTS + /* + * Re-check after vm_object_coalesce(): there must be + * no pages in the next range backed by prev_entry's + * object. Otherwise, the resulting corruption is + * same as faulting in non-zeroed page. + */ + vm_object_t obj = prev_entry->object.vm_object; + + if (vm_check_pg_zero && obj != NULL) { + struct pctrie_iter pages; + vm_page_t p; + vm_pindex_t pidx, pstart, pend; + + vm_page_iter_init(&pages, obj); + pstart = OFF_TO_IDX(prev_entry->offset + + prev_entry->end - prev_entry->start); + pend = pstart + OFF_TO_IDX(end - start), + VM_OBJECT_RLOCK(obj); + p = vm_radix_iter_lookup_ge(&pages, pstart); + if (p != NULL) { + KASSERT(p->pindex >= pend, + ("found obj %p page %p pindex %#jx " + "e %#jx %#jx %#jx %#jx", + obj, p, (uintmax_t)p->pindex, + (uintmax_t)prev_entry->offset, + (uintmax_t)prev_entry->end, + (uintmax_t)prev_entry->start, + (uintmax_t)(end - start))); + } + for (pidx = pstart; pidx < pend; pidx++) { + if (vm_pager_has_page(obj, pidx, NULL, NULL)) { + KASSERT(1, ("found pager obj %p " + "pindex %#jx " + "e %#jx %#jx %#jx %#jx", + obj, (uintmax_t)pidx, + (uintmax_t)prev_entry->offset, + (uintmax_t)prev_entry->end, + (uintmax_t)prev_entry->start, + (uintmax_t)(end - start))); + } + } + VM_OBJECT_RUNLOCK(obj); + } +#endif + /* * We were able to extend the object. Determine if we * can extend the previous map entry to include the 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 @@ -2190,8 +2190,8 @@ next_size >>= PAGE_SHIFT; next_pindex = OFF_TO_IDX(prev_offset) + prev_size; - if (prev_object->ref_count > 1 && - prev_object->size != next_pindex && + if (prev_object->ref_count > 1 || + prev_object->size != next_pindex || (prev_object->flags & OBJ_ONEMAPPING) == 0) { VM_OBJECT_WUNLOCK(prev_object); return (FALSE); @@ -2223,26 +2223,13 @@ * Remove any pages that may still be in the object from a previous * deallocation. */ - if (next_pindex < prev_object->size) { - vm_object_page_remove(prev_object, next_pindex, next_pindex + - next_size, 0); -#if 0 - if (prev_object->cred != NULL) { - KASSERT(prev_object->charge >= - ptoa(prev_object->size - next_pindex), - ("object %p overcharged 1 %jx %jx", prev_object, - (uintmax_t)next_pindex, (uintmax_t)next_size)); - prev_object->charge -= ptoa(prev_object->size - - next_pindex); - } -#endif - } + vm_object_page_remove(prev_object, next_pindex, next_pindex + + next_size, 0); /* - * Extend the object if necessary. + * Extend the object. */ - if (next_pindex + next_size > prev_object->size) - prev_object->size = next_pindex + next_size; + prev_object->size = next_pindex + next_size; VM_OBJECT_WUNLOCK(prev_object); return (TRUE);