Revert change in revision 1.53 and add a small comment to protect
the revived code. vm pages newly allocated are marked busy (PG_BUSY), thus calling vm_page_delete before the pages has been freed or unbusied will cause a deadlock since vm_page_object_page_remove will wait for the busy flag to be cleared. This can be triggered by calling malloc with size > PAGE_SIZE and the M_NOWAIT flag on systems low on physical free memory. A kernel module that reproduces the problem, written by Logan Gabriel <logan@mail.2cactus.com>, can be found in the freebsd-hackers mail archive (12 Apr 2001). The problem was recently noticed again by Archie Cobbs <archie@dellroad.org>. Reviewed by: dillon
This commit is contained in:
parent
3adb054e5a
commit
a814ebd3df
@ -378,6 +378,18 @@ retry:
|
|||||||
vm_map_lock(map);
|
vm_map_lock(map);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Free the pages before removing the map entry.
|
||||||
|
* They are already marked busy. Calling
|
||||||
|
* vm_map_delete before the pages has been freed or
|
||||||
|
* unbusied will cause a deadlock.
|
||||||
|
*/
|
||||||
|
while (i != 0) {
|
||||||
|
i -= PAGE_SIZE;
|
||||||
|
m = vm_page_lookup(kmem_object,
|
||||||
|
OFF_TO_IDX(offset + i));
|
||||||
|
vm_page_free(m);
|
||||||
|
}
|
||||||
vm_map_delete(map, addr, addr + size);
|
vm_map_delete(map, addr, addr + size);
|
||||||
vm_map_unlock(map);
|
vm_map_unlock(map);
|
||||||
goto bad;
|
goto bad;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user