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,51 @@ * 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; + +#ifdef INVARIANTS + /* + * Re-check: 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. + */ + if (vm_check_pg_zero) { + vm_page_t m; + vm_pindex_t pidx, pstart, pend; + + pstart = OFF_TO_IDX(prev_offset + prev_size); + pend = pstart + OFF_TO_IDX(next_size), + m = vm_radix_lookup_ge(&prev_object->rtree, pstart); + if (m != NULL) { + KASSERT(m->pindex >= pend, + ("found obj %p page %p pindex %#jx " + "e %#jx %#jx %#jx", + prev_object, m, (uintmax_t)m->pindex, + (uintmax_t)prev_offset, + (uintmax_t)prev_size, + (uintmax_t)next_size)); + } + for (pidx = pstart; pidx < pend; pidx++) { + if (vm_pager_has_page(prev_object, pidx, + NULL, NULL)) { + KASSERT(1, ("found pager obj %p " + "pindex %#jx " + "e %#jx %#jx %#jx", + prev_object, (uintmax_t)pidx, + (uintmax_t)prev_offset, + (uintmax_t)prev_size, + (uintmax_t)next_size)); + } + } + } +#endif VM_OBJECT_WUNLOCK(prev_object); return (TRUE);