Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 Aug 2014 21:21:30 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r270630 - stable/10/sys/vm
Message-ID:  <201408252121.s7PLLUlC043683@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Mon Aug 25 21:21:29 2014
New Revision: 270630
URL: http://svnweb.freebsd.org/changeset/base/270630

Log:
  MFC r270011:
  Implement 'fast path' for the vm page fault handler.
  
  MFC r270387 (by alc):
  Relax one of the conditions for mapping a page on the fast path.
  
  Approved by:	re (gjb)

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

Modified: stable/10/sys/vm/vm_fault.c
==============================================================================
--- stable/10/sys/vm/vm_fault.c	Mon Aug 25 21:19:08 2014	(r270629)
+++ stable/10/sys/vm/vm_fault.c	Mon Aug 25 21:21:29 2014	(r270630)
@@ -237,6 +237,7 @@ vm_fault_hold(vm_map_t map, vm_offset_t 
 	int hardfault;
 	struct faultstate fs;
 	struct vnode *vp;
+	vm_page_t m;
 	int locked, error;
 
 	hardfault = 0;
@@ -290,6 +291,56 @@ RetryFault:;
 		goto RetryFault;
 	}
 
+	if (wired)
+		fault_type = prot | (fault_type & VM_PROT_COPY);
+
+	if (fs.vp == NULL /* avoid locked vnode leak */ &&
+	    (fault_flags & (VM_FAULT_CHANGE_WIRING | VM_FAULT_DIRTY)) == 0 &&
+	    /* avoid calling vm_object_set_writeable_dirty() */
+	    ((prot & VM_PROT_WRITE) == 0 ||
+	    fs.first_object->type != OBJT_VNODE ||
+	    (fs.first_object->flags & OBJ_MIGHTBEDIRTY) != 0)) {
+		VM_OBJECT_RLOCK(fs.first_object);
+		if ((prot & VM_PROT_WRITE) != 0 &&
+		    fs.first_object->type == OBJT_VNODE &&
+		    (fs.first_object->flags & OBJ_MIGHTBEDIRTY) == 0)
+			goto fast_failed;
+		m = vm_page_lookup(fs.first_object, fs.first_pindex);
+		/* A busy page can be mapped for read|execute access. */
+		if (m == NULL || ((prot & VM_PROT_WRITE) != 0 &&
+		    vm_page_busied(m)) || m->valid != VM_PAGE_BITS_ALL)
+			goto fast_failed;
+		result = pmap_enter(fs.map->pmap, vaddr, m, prot,
+		   fault_type | PMAP_ENTER_NOSLEEP | (wired ? PMAP_ENTER_WIRED :
+		   0), 0);
+		if (result != KERN_SUCCESS)
+			goto fast_failed;
+		if (m_hold != NULL) {
+			*m_hold = m;
+			vm_page_lock(m);
+			vm_page_hold(m);
+			vm_page_unlock(m);
+		}
+		if ((fault_type & VM_PROT_WRITE) != 0 &&
+		    (m->oflags & VPO_UNMANAGED) == 0) {
+			vm_page_dirty(m);
+			vm_pager_page_unswapped(m);
+		}
+		VM_OBJECT_RUNLOCK(fs.first_object);
+		if (!wired)
+			vm_fault_prefault(&fs, vaddr, 0, 0);
+		vm_map_lookup_done(fs.map, fs.entry);
+		curthread->td_ru.ru_minflt++;
+		return (KERN_SUCCESS);
+fast_failed:
+		if (!VM_OBJECT_TRYUPGRADE(fs.first_object)) {
+			VM_OBJECT_RUNLOCK(fs.first_object);
+			VM_OBJECT_WLOCK(fs.first_object);
+		}
+	} else {
+		VM_OBJECT_WLOCK(fs.first_object);
+	}
+
 	/*
 	 * Make a reference to this object to prevent its disposal while we
 	 * are messing with it.  Once we have the reference, the map is free
@@ -300,15 +351,11 @@ RetryFault:;
 	 * truncation operations) during I/O.  This must be done after
 	 * obtaining the vnode lock in order to avoid possible deadlocks.
 	 */
-	VM_OBJECT_WLOCK(fs.first_object);
 	vm_object_reference_locked(fs.first_object);
 	vm_object_pip_add(fs.first_object, 1);
 
 	fs.lookup_still_valid = TRUE;
 
-	if (wired)
-		fault_type = prot | (fault_type & VM_PROT_COPY);
-
 	fs.first_m = NULL;
 
 	/*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201408252121.s7PLLUlC043683>