svn commit: r355082 - head/sys/vm

Jeff Roberson jeff at FreeBSD.org
Mon Nov 25 07:13:05 UTC 2019


Author: jeff
Date: Mon Nov 25 07:13:05 2019
New Revision: 355082
URL: https://svnweb.freebsd.org/changeset/base/355082

Log:
  Move anonymous object copying for fork into its own routine and so that we
  can avoid locking non-anonymous objects.
  
  Reviewed by:	kib
  Differential Revision:	https://reviews.freebsd.org/D22472

Modified:
  head/sys/vm/vm_map.c

Modified: head/sys/vm/vm_map.c
==============================================================================
--- head/sys/vm/vm_map.c	Mon Nov 25 06:16:53 2019	(r355081)
+++ head/sys/vm/vm_map.c	Mon Nov 25 07:13:05 2019	(r355082)
@@ -3722,7 +3722,57 @@ vm_map_check_protection(vm_map_t map, vm_offset_t star
 	return (TRUE);
 }
 
+
 /*
+ *
+ *	vm_map_copy_anon_object:
+ *
+ *	Copies an anonymous object from an existing map entry to a
+ *	new one.  Carries forward the swap charge.  May change the
+ *	src object on return.
+ */
+static void
+vm_map_copy_anon_object(vm_map_entry_t src_entry, vm_map_entry_t dst_entry,
+    vm_offset_t size, vm_ooffset_t *fork_charge)
+{
+	vm_object_t src_object;
+	struct ucred *cred;
+	int charged;
+
+	src_object = src_entry->object.vm_object;
+	VM_OBJECT_WLOCK(src_object);
+	charged = ENTRY_CHARGED(src_entry);
+	vm_object_collapse(src_object);
+	if ((src_object->flags & OBJ_ONEMAPPING) != 0) {
+		vm_object_split(src_entry);
+		src_object = src_entry->object.vm_object;
+	}
+	vm_object_reference_locked(src_object);
+	vm_object_clear_flag(src_object, OBJ_ONEMAPPING);
+	if (src_entry->cred != NULL &&
+	    !(src_entry->eflags & MAP_ENTRY_NEEDS_COPY)) {
+		KASSERT(src_object->cred == NULL,
+		    ("OVERCOMMIT: vm_map_copy_anon_entry: cred %p",
+		     src_object));
+		src_object->cred = src_entry->cred;
+		src_object->charge = size;
+	}
+	VM_OBJECT_WUNLOCK(src_object);
+	dst_entry->object.vm_object = src_object;
+	if (charged) {
+		cred = curthread->td_ucred;
+		crhold(cred);
+		dst_entry->cred = cred;
+		*fork_charge += size;
+		if (!(src_entry->eflags & MAP_ENTRY_NEEDS_COPY)) {
+			crhold(cred);
+			src_entry->cred = cred;
+			*fork_charge += size;
+		}
+	}
+}
+
+/*
  *	vm_map_copy_entry:
  *
  *	Copies the contents of the source entry to the destination
@@ -3739,8 +3789,6 @@ vm_map_copy_entry(
 	vm_object_t src_object;
 	vm_map_entry_t fake_entry;
 	vm_offset_t size;
-	struct ucred *cred;
-	int charged;
 
 	VM_MAP_ASSERT_LOCKED(dst_map);
 
@@ -3766,39 +3814,14 @@ vm_map_copy_entry(
 		 */
 		size = src_entry->end - src_entry->start;
 		if ((src_object = src_entry->object.vm_object) != NULL) {
-			VM_OBJECT_WLOCK(src_object);
-			charged = ENTRY_CHARGED(src_entry);
 			if ((src_object->flags & OBJ_ANON) != 0) {
-				vm_object_collapse(src_object);
-				if ((src_object->flags & OBJ_ONEMAPPING) != 0) {
-					vm_object_split(src_entry);
-					src_object =
-					    src_entry->object.vm_object;
-				}
-			}
-			vm_object_reference_locked(src_object);
-			vm_object_clear_flag(src_object, OBJ_ONEMAPPING);
-			if (src_entry->cred != NULL &&
-			    !(src_entry->eflags & MAP_ENTRY_NEEDS_COPY)) {
-				KASSERT(src_object->cred == NULL,
-				    ("OVERCOMMIT: vm_map_copy_entry: cred %p",
-				     src_object));
-				src_object->cred = src_entry->cred;
-				src_object->charge = size;
-			}
-			VM_OBJECT_WUNLOCK(src_object);
-			dst_entry->object.vm_object = src_object;
-			if (charged) {
-				cred = curthread->td_ucred;
-				crhold(cred);
-				dst_entry->cred = cred;
-				*fork_charge += size;
-				if (!(src_entry->eflags &
-				      MAP_ENTRY_NEEDS_COPY)) {
-					crhold(cred);
-					src_entry->cred = cred;
-					*fork_charge += size;
-				}
+				vm_map_copy_anon_object(src_entry, dst_entry,
+				    size, fork_charge);
+				/* May have split/collapsed, reload obj. */
+				src_object = src_entry->object.vm_object;
+			} else {
+				vm_object_reference(src_object);
+				dst_entry->object.vm_object = src_object;
 			}
 			src_entry->eflags |= MAP_ENTRY_COW |
 			    MAP_ENTRY_NEEDS_COPY;


More information about the svn-src-all mailing list