svn commit: r357025 - head/sys/vm

Jeff Roberson jeff at FreeBSD.org
Thu Jan 23 05:18:01 UTC 2020


Author: jeff
Date: Thu Jan 23 05:18:00 2020
New Revision: 357025
URL: https://svnweb.freebsd.org/changeset/base/357025

Log:
  (fault 6/9) Move getpages and associated logic into a dedicated function.
  
  Reviewed by:	kib
  Differential Revision:	https://reviews.freebsd.org/D23311

Modified:
  head/sys/vm/vm_fault.c

Modified: head/sys/vm/vm_fault.c
==============================================================================
--- head/sys/vm/vm_fault.c	Thu Jan 23 05:14:41 2020	(r357024)
+++ head/sys/vm/vm_fault.c	Thu Jan 23 05:18:00 2020	(r357025)
@@ -1001,7 +1001,96 @@ vm_fault_next(struct faultstate *fs)
 	return (true);
 }
 
+
 /*
+ * Call the pager to retrieve the page if there is a chance
+ * that the pager has it, and potentially retrieve additional
+ * pages at the same time.
+ */
+static int
+vm_fault_getpages(struct faultstate *fs, int nera, int *behindp, int *aheadp)
+{
+	vm_offset_t e_end, e_start;
+	int ahead, behind, cluster_offset, rv;
+	u_char behavior;
+
+	/*
+	 * Prepare for unlocking the map.  Save the map
+	 * entry's start and end addresses, which are used to
+	 * optimize the size of the pager operation below.
+	 * Even if the map entry's addresses change after
+	 * unlocking the map, using the saved addresses is
+	 * safe.
+	 */
+	e_start = fs->entry->start;
+	e_end = fs->entry->end;
+	behavior = vm_map_entry_behavior(fs->entry);
+
+	/*
+	 * Release the map lock before locking the vnode or
+	 * sleeping in the pager.  (If the current object has
+	 * a shadow, then an earlier iteration of this loop
+	 * may have already unlocked the map.)
+	 */
+	unlock_map(fs);
+
+	rv = vm_fault_lock_vnode(fs, false);
+	MPASS(rv == KERN_SUCCESS || rv == KERN_RESOURCE_SHORTAGE);
+	if (rv == KERN_RESOURCE_SHORTAGE)
+		return (rv);
+	KASSERT(fs->vp == NULL || !fs->map->system_map,
+	    ("vm_fault: vnode-backed object mapped by system map"));
+
+	/*
+	 * Page in the requested page and hint the pager,
+	 * that it may bring up surrounding pages.
+	 */
+	if (nera == -1 || behavior == MAP_ENTRY_BEHAV_RANDOM ||
+	    P_KILLED(curproc)) {
+		behind = 0;
+		ahead = 0;
+	} else {
+		/* Is this a sequential fault? */
+		if (nera > 0) {
+			behind = 0;
+			ahead = nera;
+		} else {
+			/*
+			 * Request a cluster of pages that is
+			 * aligned to a VM_FAULT_READ_DEFAULT
+			 * page offset boundary within the
+			 * object.  Alignment to a page offset
+			 * boundary is more likely to coincide
+			 * with the underlying file system
+			 * block than alignment to a virtual
+			 * address boundary.
+			 */
+			cluster_offset = fs->pindex % VM_FAULT_READ_DEFAULT;
+			behind = ulmin(cluster_offset,
+			    atop(fs->vaddr - e_start));
+			ahead = VM_FAULT_READ_DEFAULT - 1 - cluster_offset;
+		}
+		ahead = ulmin(ahead, atop(e_end - fs->vaddr) - 1);
+	}
+	*behindp = behind;
+	*aheadp = ahead;
+	rv = vm_pager_get_pages(fs->object, &fs->m, 1, behindp, aheadp);
+	if (rv == VM_PAGER_OK)
+		return (KERN_SUCCESS);
+	if (rv == VM_PAGER_ERROR)
+		printf("vm_fault: pager read error, pid %d (%s)\n",
+		    curproc->p_pid, curproc->p_comm);
+	/*
+	 * If an I/O error occurred or the requested page was
+	 * outside the range of the pager, clean up and return
+	 * an error.
+	 */
+	if (rv == VM_PAGER_ERROR || rv == VM_PAGER_BAD)
+		return (KERN_OUT_OF_BOUNDS);
+	return (KERN_NOT_RECEIVER);
+}
+
+/*
  * 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
  * read busy for pageouts (and even pageins if it is the vnode pager),
@@ -1043,10 +1132,8 @@ vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fa
 {
 	struct faultstate fs;
 	struct domainset *dset;
-	vm_offset_t e_end, e_start;
-	int ahead, alloc_req, behind, cluster_offset, faultcount;
+	int ahead, alloc_req, behind, faultcount;
 	int nera, oom, result, rv;
-	u_char behavior;
 	bool dead, hardfault;
 
 	VM_CNT_INC(v_vm_faults);
@@ -1282,104 +1369,28 @@ readrest:
 		 * have the page, the number of additional pages to read will
 		 * apply to subsequent objects in the shadow chain.
 		 */
-		if (nera == -1 && !P_KILLED(curproc)) {
+		if (nera == -1 && !P_KILLED(curproc))
 			nera = vm_fault_readahead(&fs);
-			/*
-			 * Prepare for unlocking the map.  Save the map
-			 * entry's start and end addresses, which are used to
-			 * optimize the size of the pager operation below.
-			 * Even if the map entry's addresses change after
-			 * unlocking the map, using the saved addresses is
-			 * safe.
-			 */
-			e_start = fs.entry->start;
-			e_end = fs.entry->end;
-			behavior = vm_map_entry_behavior(fs.entry);
-		}
 
-		/*
-		 * Call the pager to retrieve the page if there is a chance
-		 * that the pager has it, and potentially retrieve additional
-		 * pages at the same time.
-		 */
-		if (fs.object->type != OBJT_DEFAULT) {
-			/*
-			 * Release the map lock before locking the vnode or
-			 * sleeping in the pager.  (If the current object has
-			 * a shadow, then an earlier iteration of this loop
-			 * may have already unlocked the map.)
-			 */
-			unlock_map(&fs);
-
-			rv = vm_fault_lock_vnode(&fs, false);
-			MPASS(rv == KERN_SUCCESS ||
-			    rv == KERN_RESOURCE_SHORTAGE);
-			if (rv == KERN_RESOURCE_SHORTAGE)
-				goto RetryFault;
-			KASSERT(fs.vp == NULL || !fs.map->system_map,
-			    ("vm_fault: vnode-backed object mapped by system map"));
-
-			/*
-			 * Page in the requested page and hint the pager,
-			 * that it may bring up surrounding pages.
-			 */
-			if (nera == -1 || behavior == MAP_ENTRY_BEHAV_RANDOM ||
-			    P_KILLED(curproc)) {
-				behind = 0;
-				ahead = 0;
-			} else {
-				/* Is this a sequential fault? */
-				if (nera > 0) {
-					behind = 0;
-					ahead = nera;
-				} else {
-					/*
-					 * Request a cluster of pages that is
-					 * aligned to a VM_FAULT_READ_DEFAULT
-					 * page offset boundary within the
-					 * object.  Alignment to a page offset
-					 * boundary is more likely to coincide
-					 * with the underlying file system
-					 * block than alignment to a virtual
-					 * address boundary.
-					 */
-					cluster_offset = fs.pindex %
-					    VM_FAULT_READ_DEFAULT;
-					behind = ulmin(cluster_offset,
-					    atop(vaddr - e_start));
-					ahead = VM_FAULT_READ_DEFAULT - 1 -
-					    cluster_offset;
-				}
-				ahead = ulmin(ahead, atop(e_end - vaddr) - 1);
-			}
-			rv = vm_pager_get_pages(fs.object, &fs.m, 1,
-			    &behind, &ahead);
-			if (rv == VM_PAGER_OK) {
-				faultcount = behind + 1 + ahead;
-				hardfault = true;
-				break; /* break to PAGE HAS BEEN FOUND. */
-			}
-			VM_OBJECT_WLOCK(fs.object);
-			if (rv == VM_PAGER_ERROR)
-				printf("vm_fault: pager read error, pid %d (%s)\n",
-				    curproc->p_pid, curproc->p_comm);
-
-			/*
-			 * If an I/O error occurred or the requested page was
-			 * outside the range of the pager, clean up and return
-			 * an error.
-			 */
-			if (rv == VM_PAGER_ERROR || rv == VM_PAGER_BAD) {
-				fault_page_free(&fs.m);
-				unlock_and_deallocate(&fs);
-				return (KERN_OUT_OF_BOUNDS);
-			}
-
+		rv = vm_fault_getpages(&fs, nera, &behind, &ahead);
+		if (rv == KERN_SUCCESS) {
+			faultcount = behind + 1 + ahead;
+			hardfault = true;
+			break; /* break to PAGE HAS BEEN FOUND. */
 		}
+		if (rv == KERN_RESOURCE_SHORTAGE)
+			goto RetryFault;
+		VM_OBJECT_WLOCK(fs.object);
+		if (rv == KERN_OUT_OF_BOUNDS) {
+			fault_page_free(&fs.m);
+			unlock_and_deallocate(&fs);
+			return (rv);
+		}
 
 		/*
-		 * The page was not found in the current object.  Try to traverse
-		 * into a backing object or zero fill if none is found.
+		 * The page was not found in the current object.  Try to
+		 * traverse into a backing object or zero fill if none is
+		 * found.
 		 */
 		if (!vm_fault_next(&fs)) {
 			/* Don't try to prefault neighboring pages. */


More information about the svn-src-head mailing list