vm_object_split(): Handle orig_object type changes.
orig_object->type can change from OBJT_DEFAULT to OBJT_SWAP while vm_object_split() is sleeping. In this case some pages in new_object may be left unbusied, but vm_object_split() attempts to unbusy all of them. Track the beginning of the busied range. Add an assertion to verify that pages are not re-added to the source object while sleeping. Reported by: Olympios Petrakis <olympios.petrakis@netapp.com> Reviewed by: alc, kib Tested by: pho MFC after: 1 week Sponsored by: NetApp, Inc. Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D26223
This commit is contained in:
parent
7de1bc13e2
commit
aec9e7d8b0
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=365437
@ -1496,7 +1496,7 @@ vm_object_shadow(vm_object_t *object, vm_ooffset_t *offset, vm_size_t length,
|
||||
void
|
||||
vm_object_split(vm_map_entry_t entry)
|
||||
{
|
||||
vm_page_t m, m_next;
|
||||
vm_page_t m, m_busy, m_next;
|
||||
vm_object_t orig_object, new_object, backing_object;
|
||||
vm_pindex_t idx, offidxstart;
|
||||
vm_size_t size;
|
||||
@ -1553,8 +1553,14 @@ vm_object_split(vm_map_entry_t entry)
|
||||
* that the object is in transition.
|
||||
*/
|
||||
vm_object_set_flag(orig_object, OBJ_SPLIT);
|
||||
m_busy = NULL;
|
||||
#ifdef INVARIANTS
|
||||
idx = 0;
|
||||
#endif
|
||||
retry:
|
||||
m = vm_page_find_least(orig_object, offidxstart);
|
||||
KASSERT(m == NULL || idx <= m->pindex - offidxstart,
|
||||
("%s: object %p was repopulated", __func__, orig_object));
|
||||
for (; m != NULL && (idx = m->pindex - offidxstart) < size;
|
||||
m = m_next) {
|
||||
m_next = TAILQ_NEXT(m, listq);
|
||||
@ -1609,8 +1615,15 @@ vm_object_split(vm_map_entry_t entry)
|
||||
*/
|
||||
vm_reserv_rename(m, new_object, orig_object, offidxstart);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* orig_object's type may change while sleeping, so keep track
|
||||
* of the beginning of the busied range.
|
||||
*/
|
||||
if (orig_object->type != OBJT_SWAP)
|
||||
vm_page_xunbusy(m);
|
||||
else if (m_busy == NULL)
|
||||
m_busy = m;
|
||||
}
|
||||
if (orig_object->type == OBJT_SWAP) {
|
||||
/*
|
||||
@ -1618,8 +1631,9 @@ vm_object_split(vm_map_entry_t entry)
|
||||
* and new_object's locks are released and reacquired.
|
||||
*/
|
||||
swap_pager_copy(orig_object, new_object, offidxstart, 0);
|
||||
TAILQ_FOREACH(m, &new_object->memq, listq)
|
||||
vm_page_xunbusy(m);
|
||||
if (m_busy != NULL)
|
||||
TAILQ_FOREACH_FROM(m_busy, &new_object->memq, listq)
|
||||
vm_page_xunbusy(m_busy);
|
||||
}
|
||||
vm_object_clear_flag(orig_object, OBJ_SPLIT);
|
||||
VM_OBJECT_WUNLOCK(orig_object);
|
||||
|
Loading…
Reference in New Issue
Block a user