svn commit: r305803 - stable/10/sys/vm

Konstantin Belousov kib at FreeBSD.org
Wed Sep 14 10:51:07 UTC 2016


Author: kib
Date: Wed Sep 14 10:51:06 2016
New Revision: 305803
URL: https://svnweb.freebsd.org/changeset/base/305803

Log:
  MFC r305129:
  Make swapoff reliable.

Modified:
  stable/10/sys/vm/swap_pager.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/vm/swap_pager.c
==============================================================================
--- stable/10/sys/vm/swap_pager.c	Wed Sep 14 10:36:44 2016	(r305802)
+++ stable/10/sys/vm/swap_pager.c	Wed Sep 14 10:51:06 2016	(r305803)
@@ -1764,36 +1764,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;
 
 	GIANT_REQUIRED;
 
 	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-all mailing list