svn commit: r357022 - head/sys/vm

Jeff Roberson jeff at FreeBSD.org
Thu Jan 23 05:07:02 UTC 2020


Author: jeff
Date: Thu Jan 23 05:07:01 2020
New Revision: 357022
URL: https://svnweb.freebsd.org/changeset/base/357022

Log:
  (fault 3/9) Move map relookup into a dedicated function.
  
  Add a new VM return code KERN_RESTART which means, deallocate and restart in
  fault.
  
  Reviewed by:	kib, markj
  Differential Revision:	https://reviews.freebsd.org/D23303

Modified:
  head/sys/vm/vm_fault.c
  head/sys/vm/vm_param.h

Modified: head/sys/vm/vm_fault.c
==============================================================================
--- head/sys/vm/vm_fault.c	Thu Jan 23 05:05:39 2020	(r357021)
+++ head/sys/vm/vm_fault.c	Thu Jan 23 05:07:01 2020	(r357022)
@@ -795,6 +795,57 @@ vm_fault_lookup(struct faultstate *fs)
 	return (KERN_SUCCESS);
 }
 
+static int
+vm_fault_relookup(struct faultstate *fs)
+{
+	vm_object_t retry_object;
+	vm_pindex_t retry_pindex;
+	vm_prot_t retry_prot;
+	int result;
+
+	if (!vm_map_trylock_read(fs->map))
+		return (KERN_RESTART);
+
+	fs->lookup_still_valid = true;
+	if (fs->map->timestamp == fs->map_generation)
+		return (KERN_SUCCESS);
+
+	result = vm_map_lookup_locked(&fs->map, fs->vaddr, fs->fault_type,
+	    &fs->entry, &retry_object, &retry_pindex, &retry_prot,
+	    &fs->wired);
+	if (result != KERN_SUCCESS) {
+		/*
+		 * If retry of map lookup would have blocked then
+		 * retry fault from start.
+		 */
+		if (result == KERN_FAILURE)
+			return (KERN_RESTART);
+		return (result);
+	}
+	if (retry_object != fs->first_object ||
+	    retry_pindex != fs->first_pindex)
+		return (KERN_RESTART);
+
+	/*
+	 * Check whether the protection has changed or the object has
+	 * been copied while we left the map unlocked. Changing from
+	 * read to write permission is OK - we leave the page
+	 * write-protected, and catch the write fault. Changing from
+	 * write to read permission means that we can't mark the page
+	 * write-enabled after all.
+	 */
+	fs->prot &= retry_prot;
+	fs->fault_type &= retry_prot;
+	if (fs->prot == 0)
+		return (KERN_RESTART);
+
+	/* Reassert because wired may have changed. */
+	KASSERT(fs->wired || (fs->fault_flags & VM_FAULT_WIRE) == 0,
+	    ("!wired && VM_FAULT_WIRE"));
+
+	return (KERN_SUCCESS);
+}
+
 /*
  * Wait/Retry if the page is busy.  We have to do this if the page is
  * either exclusive or shared busy because the vm_pager may be using
@@ -837,10 +888,8 @@ vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fa
 {
 	struct faultstate fs;
 	struct domainset *dset;
-	vm_object_t next_object, retry_object;
+	vm_object_t next_object;
 	vm_offset_t e_end, e_start;
-	vm_pindex_t retry_pindex;
-	vm_prot_t retry_prot;
 	int ahead, alloc_req, behind, cluster_offset, faultcount;
 	int nera, oom, result, rv;
 	u_char behavior;
@@ -1363,56 +1412,12 @@ next:
 	 * lookup.
 	 */
 	if (!fs.lookup_still_valid) {
-		if (!vm_map_trylock_read(fs.map)) {
+		result = vm_fault_relookup(&fs);
+		if (result != KERN_SUCCESS) {
 			fault_deallocate(&fs);
-			goto RetryFault;
-		}
-		fs.lookup_still_valid = true;
-		if (fs.map->timestamp != fs.map_generation) {
-			result = vm_map_lookup_locked(&fs.map, vaddr, fs.fault_type,
-			    &fs.entry, &retry_object, &retry_pindex, &retry_prot,
-			    &fs.wired);
-
-			/*
-			 * If we don't need the page any longer, put it on the inactive
-			 * list (the easiest thing to do here).  If no one needs it,
-			 * pageout will grab it eventually.
-			 */
-			if (result != KERN_SUCCESS) {
-				fault_deallocate(&fs);
-
-				/*
-				 * If retry of map lookup would have blocked then
-				 * retry fault from start.
-				 */
-				if (result == KERN_FAILURE)
-					goto RetryFault;
-				return (result);
-			}
-			if ((retry_object != fs.first_object) ||
-			    (retry_pindex != fs.first_pindex)) {
-				fault_deallocate(&fs);
+			if (result == KERN_RESTART)
 				goto RetryFault;
-			}
-
-			/*
-			 * Check whether the protection has changed or the object has
-			 * been copied while we left the map unlocked. Changing from
-			 * read to write permission is OK - we leave the page
-			 * write-protected, and catch the write fault. Changing from
-			 * write to read permission means that we can't mark the page
-			 * write-enabled after all.
-			 */
-			fs.prot &= retry_prot;
-			fs.fault_type &= retry_prot;
-			if (fs.prot == 0) {
-				fault_deallocate(&fs);
-				goto RetryFault;
-			}
-
-			/* Reassert because wired may have changed. */
-			KASSERT(fs.wired || (fs.fault_flags & VM_FAULT_WIRE) == 0,
-			    ("!wired && VM_FAULT_WIRE"));
+			return (result);
 		}
 	}
 	VM_OBJECT_ASSERT_UNLOCKED(fs.object);

Modified: head/sys/vm/vm_param.h
==============================================================================
--- head/sys/vm/vm_param.h	Thu Jan 23 05:05:39 2020	(r357021)
+++ head/sys/vm/vm_param.h	Thu Jan 23 05:07:01 2020	(r357022)
@@ -114,6 +114,7 @@ struct xswdev {
 #define	KERN_NOT_RECEIVER	7
 #define	KERN_NO_ACCESS		8
 #define	KERN_OUT_OF_BOUNDS	9
+#define	KERN_RESTART		10
 
 #ifndef PA_LOCK_COUNT
 #ifdef SMP


More information about the svn-src-head mailing list