Fix the last known race in swapoff(), which could lead to a spurious panic:

swapoff: failed to locate %d swap blocks

The race occurred because putpages() can block between the time it
allocates swap space and the time it updates the swap metadata to
associate that space with a vm_object, so swapoff() would complain
about the temporary inconsistency.  I hoped to fix this by making
swp_pager_getswapspace() and swp_pager_meta_build() a single atomic
operation, but that proved to be inconvenient.  With this change,
swapoff() simply doesn't attempt to be so clever about detecting when
all the pageout activity to the target device should have drained.
This commit is contained in:
David Schultz 2004-11-06 07:17:50 +00:00
parent 550b156641
commit 8bc61209d4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=137299

View File

@ -1666,13 +1666,12 @@ static void
swap_pager_swapoff(struct swdevt *sp)
{
struct swblock *swap;
vm_object_t waitobj;
int i, j;
int i, j, retries;
GIANT_REQUIRED;
retries = 0;
full_rescan:
waitobj = NULL;
mtx_lock(&swhash_mtx);
for (i = 0; i <= swhash_mask; i++) { /* '<=' is correct here */
restart:
@ -1683,7 +1682,6 @@ swap_pager_swapoff(struct swdevt *sp)
if (swp_pager_isondev(swap->swb_pages[j], sp)) {
/* avoid deadlock */
if (!VM_OBJECT_TRYLOCK(object)) {
waitobj = object;
break;
} else {
mtx_unlock(&swhash_mtx);
@ -1695,30 +1693,25 @@ swap_pager_swapoff(struct swdevt *sp)
}
}
}
if (object->paging_in_progress)
waitobj = object;
}
}
mtx_unlock(&swhash_mtx);
if (waitobj && sp->sw_used) {
if (sp->sw_used) {
int dummy;
/*
* The most likely reason we will have to do another pass is
* that something is being paged out to the device being
* removed. This can't happen forever because new allocations
* will not be made on this device, but we still need to wait
* for the activity to finish. We have no way of knowing
* which objects we need to wait for, so we pick an arbitrary
* object that is paging and hope that it finishes paging at
* about the same time as one of the objects we care about.
*
* XXX Unfortunately, our waitobj reference might not be valid
* anymore, so we also retry after 50 ms.
* Objects may be locked or paging to the device being
* removed, so we will miss their pages and need to
* make another pass. We have marked this device as
* SW_CLOSING, so the activity should finish soon.
*/
tsleep(waitobj, PVM, "swpoff", hz / 20);
retries++;
if (retries > 100) {
panic("swapoff: failed to locate %d swap blocks",
sp->sw_used);
}
tsleep(&dummy, PVM, "swpoff", hz / 20);
goto full_rescan;
}
if (sp->sw_used)
panic("swapoff: failed to locate %d swap blocks", sp->sw_used);
}
/************************************************************************