Make swapoff reliable.
The swap_pager_swapoff() function uses trylock for the object lock before pagein, which means that either i/o to md(4) over swap, or intensive page faults over swap pager objects might prevent swapoff() from making any progress. Then the retry < 100 check fails and machine panics. If trylock fails, acquire the object lock in the blockable way and restart the hash bucket walk. Keep retries logic for now. Reported and tested by: pho Reviewed by: alc, markj Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D7688
This commit is contained in:
parent
d953ec3222
commit
9815066425
@ -1688,36 +1688,49 @@ static void
|
||||
swap_pager_swapoff(struct swdevt *sp)
|
||||
{
|
||||
struct swblock *swap;
|
||||
vm_object_t locked_obj, object;
|
||||
vm_pindex_t pindex;
|
||||
int i, j, retries;
|
||||
|
||||
sx_assert(&swdev_syscall_lock, SA_XLOCKED);
|
||||
|
||||
retries = 0;
|
||||
locked_obj = NULL;
|
||||
full_rescan:
|
||||
mtx_lock(&swhash_mtx);
|
||||
for (i = 0; i <= swhash_mask; i++) { /* '<=' is correct here */
|
||||
restart:
|
||||
for (swap = swhash[i]; swap != NULL; swap = swap->swb_hnext) {
|
||||
vm_object_t object = swap->swb_object;
|
||||
vm_pindex_t pindex = swap->swb_index;
|
||||
object = swap->swb_object;
|
||||
pindex = swap->swb_index;
|
||||
for (j = 0; j < SWAP_META_PAGES; ++j) {
|
||||
if (swp_pager_isondev(swap->swb_pages[j], sp)) {
|
||||
/* avoid deadlock */
|
||||
if (!swp_pager_isondev(swap->swb_pages[j], sp))
|
||||
continue;
|
||||
if (locked_obj != object) {
|
||||
if (locked_obj != NULL)
|
||||
VM_OBJECT_WUNLOCK(locked_obj);
|
||||
locked_obj = object;
|
||||
if (!VM_OBJECT_TRYWLOCK(object)) {
|
||||
break;
|
||||
} else {
|
||||
mtx_unlock(&swhash_mtx);
|
||||
swp_pager_force_pagein(object,
|
||||
pindex + j);
|
||||
VM_OBJECT_WUNLOCK(object);
|
||||
/* Depends on type-stability. */
|
||||
VM_OBJECT_WLOCK(object);
|
||||
mtx_lock(&swhash_mtx);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
MPASS(locked_obj == object);
|
||||
mtx_unlock(&swhash_mtx);
|
||||
swp_pager_force_pagein(object, pindex + j);
|
||||
mtx_lock(&swhash_mtx);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
}
|
||||
mtx_unlock(&swhash_mtx);
|
||||
if (locked_obj != NULL) {
|
||||
VM_OBJECT_WUNLOCK(locked_obj);
|
||||
locked_obj = NULL;
|
||||
}
|
||||
if (sp->sw_used) {
|
||||
/*
|
||||
* Objects may be locked or paging to the device being
|
||||
|
Loading…
Reference in New Issue
Block a user