svn commit: r305129 - head/sys/vm
Konstantin Belousov
kib at FreeBSD.org
Wed Aug 31 14:49:59 UTC 2016
Author: kib
Date: Wed Aug 31 14:49:58 2016
New Revision: 305129
URL: https://svnweb.freebsd.org/changeset/base/305129
Log:
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
Modified:
head/sys/vm/swap_pager.c
Modified: head/sys/vm/swap_pager.c
==============================================================================
--- head/sys/vm/swap_pager.c Wed Aug 31 13:58:32 2016 (r305128)
+++ head/sys/vm/swap_pager.c Wed Aug 31 14:49:58 2016 (r305129)
@@ -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
More information about the svn-src-head
mailing list