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:
Konstantin Belousov 2016-08-31 14:49:58 +00:00
parent d953ec3222
commit 9815066425

View File

@ -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