Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Nov 2019 00:31:14 +0000 (UTC)
From:      Jeff Roberson <jeff@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r354871 - head/sys/vm
Message-ID:  <201911200031.xAK0VEeH010302@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jeff
Date: Wed Nov 20 00:31:14 2019
New Revision: 354871
URL: https://svnweb.freebsd.org/changeset/base/354871

Log:
  Only keep anonymous objects on shadow lists.  This eliminates locking of
  globally visible objects when they are part of a backing chain.
  
  Reviewed by:	kib, markj
  Differential Revision:	https://reviews.freebsd.org/D22423

Modified:
  head/sys/vm/vm_object.c
  head/sys/vm/vm_object.h

Modified: head/sys/vm/vm_object.c
==============================================================================
--- head/sys/vm/vm_object.c	Tue Nov 19 23:30:09 2019	(r354870)
+++ head/sys/vm/vm_object.c	Wed Nov 20 00:31:14 2019	(r354871)
@@ -118,6 +118,7 @@ static boolean_t vm_object_page_remove_write(vm_page_t
 		    boolean_t *allclean);
 static void	vm_object_qcollapse(vm_object_t object);
 static void	vm_object_vndeallocate(vm_object_t object);
+static void	vm_object_backing_remove(vm_object_t object);
 
 /*
  *	Virtual memory objects maintain the actual data
@@ -651,11 +652,7 @@ doterm:
 		if (temp != NULL) {
 			KASSERT((object->flags & OBJ_TMPFS_NODE) == 0,
 			    ("shadowed tmpfs v_object 2 %p", object));
-			VM_OBJECT_WLOCK(temp);
-			LIST_REMOVE(object, shadow_list);
-			temp->shadow_count--;
-			VM_OBJECT_WUNLOCK(temp);
-			object->backing_object = NULL;
+			vm_object_backing_remove(object);
 		}
 		/*
 		 * Don't double-terminate, we could be in a termination
@@ -695,6 +692,70 @@ vm_object_destroy(vm_object_t object)
 	uma_zfree(obj_zone, object);
 }
 
+static void
+vm_object_backing_remove_locked(vm_object_t object)
+{
+	vm_object_t backing_object;
+
+	backing_object = object->backing_object;
+	VM_OBJECT_ASSERT_WLOCKED(object);
+	VM_OBJECT_ASSERT_WLOCKED(backing_object);
+
+	if ((object->flags & OBJ_SHADOWLIST) != 0) {
+		LIST_REMOVE(object, shadow_list);
+		backing_object->shadow_count--;
+		object->flags &= ~OBJ_SHADOWLIST;
+	}
+	object->backing_object = NULL;
+}
+
+static void
+vm_object_backing_remove(vm_object_t object)
+{
+	vm_object_t backing_object;
+
+	VM_OBJECT_ASSERT_WLOCKED(object);
+
+	if ((object->flags & OBJ_SHADOWLIST) != 0) {
+		backing_object = object->backing_object;
+		VM_OBJECT_WLOCK(backing_object);
+		vm_object_backing_remove_locked(object);
+		VM_OBJECT_WUNLOCK(backing_object);
+	} else
+		object->backing_object = NULL;
+}
+
+static void
+vm_object_backing_insert_locked(vm_object_t object, vm_object_t backing_object)
+{
+
+	VM_OBJECT_ASSERT_WLOCKED(object);
+
+	if ((backing_object->flags & OBJ_ANON) != 0) {
+		VM_OBJECT_ASSERT_WLOCKED(backing_object);
+		LIST_INSERT_HEAD(&backing_object->shadow_head, object,
+		    shadow_list);
+		backing_object->shadow_count++;
+		object->flags |= OBJ_SHADOWLIST;
+	}
+	object->backing_object = backing_object;
+}
+
+static void
+vm_object_backing_insert(vm_object_t object, vm_object_t backing_object)
+{
+
+	VM_OBJECT_ASSERT_WLOCKED(object);
+
+	if ((backing_object->flags & OBJ_ANON) != 0) {
+		VM_OBJECT_WLOCK(backing_object);
+		vm_object_backing_insert_locked(object, backing_object);
+		VM_OBJECT_WUNLOCK(backing_object);
+	} else
+		object->backing_object = backing_object;
+}
+
+
 /*
  *	vm_object_terminate_pages removes any remaining pageable pages
  *	from the object and resets the object to an empty state.
@@ -1250,6 +1311,12 @@ vm_object_shadow(
 	result = vm_object_allocate_anon(atop(length));
 
 	/*
+	 * Store the offset into the source object, and fix up the offset into
+	 * the new object.
+	 */
+	result->backing_object_offset = *offset;
+
+	/*
 	 * The new object shadows the source object, adding a reference to it.
 	 * Our caller changes his reference to point to the new object,
 	 * removing a reference to the source object.  Net result: no change
@@ -1259,26 +1326,18 @@ vm_object_shadow(
 	 * in order to maintain page coloring consistency in the combined 
 	 * shadowed object.
 	 */
-	result->backing_object = source;
-	/*
-	 * Store the offset into the source object, and fix up the offset into
-	 * the new object.
-	 */
-	result->backing_object_offset = *offset;
 	if (source != NULL) {
-		VM_OBJECT_WLOCK(source);
+		VM_OBJECT_WLOCK(result);
+		vm_object_backing_insert(result, source);
 		result->domain = source->domain;
-		LIST_INSERT_HEAD(&source->shadow_head, result, shadow_list);
-		source->shadow_count++;
 #if VM_NRESERVLEVEL > 0
 		result->flags |= source->flags & OBJ_COLORED;
 		result->pg_color = (source->pg_color + OFF_TO_IDX(*offset)) &
 		    ((1 << (VM_NFREEORDER - 1)) - 1);
 #endif
-		VM_OBJECT_WUNLOCK(source);
+		VM_OBJECT_WUNLOCK(result);
 	}
 
-
 	/*
 	 * Return the new things
 	 */
@@ -1326,24 +1385,26 @@ vm_object_split(vm_map_entry_t entry)
 	new_object->domain = orig_object->domain;
 	source = orig_object->backing_object;
 	if (source != NULL) {
-		VM_OBJECT_WLOCK(source);
-		if ((source->flags & OBJ_DEAD) != 0) {
+		if ((source->flags & (OBJ_ANON | OBJ_DEAD)) != 0) {
+			VM_OBJECT_WLOCK(source);
+			if ((source->flags & OBJ_DEAD) != 0) {
+				VM_OBJECT_WUNLOCK(source);
+				VM_OBJECT_WUNLOCK(orig_object);
+				VM_OBJECT_WUNLOCK(new_object);
+				vm_object_deallocate(new_object);
+				VM_OBJECT_WLOCK(orig_object);
+				return;
+			}
+			vm_object_backing_insert_locked(new_object, source);
+			vm_object_reference_locked(source);	/* for new_object */
+			vm_object_clear_flag(source, OBJ_ONEMAPPING);
 			VM_OBJECT_WUNLOCK(source);
-			VM_OBJECT_WUNLOCK(orig_object);
-			VM_OBJECT_WUNLOCK(new_object);
-			vm_object_deallocate(new_object);
-			VM_OBJECT_WLOCK(orig_object);
-			return;
+		} else {
+			vm_object_backing_insert(new_object, source);
+			vm_object_reference(source);
 		}
-		LIST_INSERT_HEAD(&source->shadow_head,
-				  new_object, shadow_list);
-		source->shadow_count++;
-		vm_object_reference_locked(source);	/* for new_object */
-		vm_object_clear_flag(source, OBJ_ONEMAPPING);
-		VM_OBJECT_WUNLOCK(source);
 		new_object->backing_object_offset = 
 			orig_object->backing_object_offset + entry->offset;
-		new_object->backing_object = source;
 	}
 	if (orig_object->cred != NULL) {
 		new_object->cred = orig_object->cred;
@@ -1756,20 +1817,15 @@ vm_object_collapse(vm_object_t object)
 			 * backing_object->backing_object moves from within 
 			 * backing_object to within object.
 			 */
-			LIST_REMOVE(object, shadow_list);
-			backing_object->shadow_count--;
-			if (backing_object->backing_object) {
-				VM_OBJECT_WLOCK(backing_object->backing_object);
-				LIST_REMOVE(backing_object, shadow_list);
-				LIST_INSERT_HEAD(
-				    &backing_object->backing_object->shadow_head,
-				    object, shadow_list);
-				/*
-				 * The shadow_count has not changed.
-				 */
-				VM_OBJECT_WUNLOCK(backing_object->backing_object);
+			vm_object_backing_remove_locked(object);
+			new_backing_object = backing_object->backing_object;
+			if (new_backing_object != NULL) {
+				VM_OBJECT_WLOCK(new_backing_object);
+				vm_object_backing_remove_locked(backing_object);
+				vm_object_backing_insert_locked(object,
+				    new_backing_object);
+				VM_OBJECT_WUNLOCK(new_backing_object);
 			}
-			object->backing_object = backing_object->backing_object;
 			object->backing_object_offset +=
 			    backing_object->backing_object_offset;
 
@@ -1807,20 +1863,13 @@ vm_object_collapse(vm_object_t object)
 			 * chain.  Deallocating backing_object will not remove
 			 * it, since its reference count is at least 2.
 			 */
-			LIST_REMOVE(object, shadow_list);
-			backing_object->shadow_count--;
+			vm_object_backing_remove_locked(object);
 
 			new_backing_object = backing_object->backing_object;
-			if ((object->backing_object = new_backing_object) != NULL) {
-				VM_OBJECT_WLOCK(new_backing_object);
-				LIST_INSERT_HEAD(
-				    &new_backing_object->shadow_head,
-				    object,
-				    shadow_list
-				);
-				new_backing_object->shadow_count++;
-				vm_object_reference_locked(new_backing_object);
-				VM_OBJECT_WUNLOCK(new_backing_object);
+			if (new_backing_object != NULL) {
+				vm_object_backing_insert(object,
+				    new_backing_object);
+				vm_object_reference(new_backing_object);
 				object->backing_object_offset +=
 					backing_object->backing_object_offset;
 			}

Modified: head/sys/vm/vm_object.h
==============================================================================
--- head/sys/vm/vm_object.h	Tue Nov 19 23:30:09 2019	(r354870)
+++ head/sys/vm/vm_object.h	Wed Nov 20 00:31:14 2019	(r354871)
@@ -192,6 +192,7 @@ struct vm_object {
 #define	OBJ_TMPFS_NODE	0x0200		/* object belongs to tmpfs VREG node */
 #define	OBJ_COLORED	0x1000		/* pg_color is defined */
 #define	OBJ_ONEMAPPING	0x2000		/* One USE (a single, non-forked) mapping flag */
+#define	OBJ_SHADOWLIST	0x4000		/* Object is on the shadow list. */
 #define	OBJ_TMPFS	0x8000		/* has tmpfs vnode allocated */
 
 /*



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