Module Name:    src
Committed By:   rmind
Date:           Sat Jun 18 21:14:43 UTC 2011

Modified Files:
        src/sys/uvm: uvm_bio.c uvm_object.c

Log Message:
- Move pre-check from uvm_obj_destroy() to ubc_purge(), keep it abstracted.
- Add comments noting the race between ubc_alloc() and ubc_purge().


To generate a diff of this commit:
cvs rdiff -u -r1.75 -r1.76 src/sys/uvm/uvm_bio.c
cvs rdiff -u -r1.9 -r1.10 src/sys/uvm/uvm_object.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/uvm/uvm_bio.c
diff -u src/sys/uvm/uvm_bio.c:1.75 src/sys/uvm/uvm_bio.c:1.76
--- src/sys/uvm/uvm_bio.c:1.75	Fri Jun 17 09:50:52 2011
+++ src/sys/uvm/uvm_bio.c	Sat Jun 18 21:14:43 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_bio.c,v 1.75 2011/06/17 09:50:52 hannken Exp $	*/
+/*	$NetBSD: uvm_bio.c,v 1.76 2011/06/18 21:14:43 rmind Exp $	*/
 
 /*
  * Copyright (c) 1998 Chuck Silvers.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.75 2011/06/17 09:50:52 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.76 2011/06/18 21:14:43 rmind Exp $");
 
 #include "opt_uvmhist.h"
 #include "opt_ubc.h"
@@ -481,12 +481,12 @@
 	slot_offset = (vaddr_t)(offset & ((voff_t)ubc_winsize - 1));
 	*lenp = MIN(*lenp, ubc_winsize - slot_offset);
 
+	mutex_enter(ubc_object.uobj.vmobjlock);
+again:
 	/*
-	 * The object is already referenced, so we do not need to add a ref.
+	 * The UVM object is already referenced.
 	 * Lock order: UBC object -> ubc_map::uobj.
 	 */
-	mutex_enter(ubc_object.uobj.vmobjlock);
-again:
 	umap = ubc_find_mapping(uobj, umap_offset);
 	if (umap == NULL) {
 		struct uvm_object *oobj;
@@ -503,10 +503,14 @@
 		oobj = umap->uobj;
 
 		/*
-		 * remove from old hash (if any), add to new hash.
+		 * Remove from old hash (if any), add to new hash.
 		 */
 
 		if (oobj != NULL) {
+			/*
+			 * Mapping must be removed before the list entry,
+			 * since there is a race with ubc_purge().
+			 */
 			if (umap->flags & UMAP_MAPPING_CACHED) {
 				umap->flags &= ~UMAP_MAPPING_CACHED;
 				mutex_enter(oobj->vmobjlock);
@@ -792,6 +796,13 @@
 
 	KASSERT(uobj->uo_npages == 0);
 
+	/*
+	 * Safe to check without lock held, as ubc_alloc() removes
+	 * the mapping and list entry in the correct order.
+	 */
+	if (__predict_true(LIST_EMPTY(&uobj->uo_ubc))) {
+		return;
+	}
 	mutex_enter(ubc_object.uobj.vmobjlock);
 	while ((umap = LIST_FIRST(&uobj->uo_ubc)) != NULL) {
 		KASSERT(umap->refcount == 0);

Index: src/sys/uvm/uvm_object.c
diff -u src/sys/uvm/uvm_object.c:1.9 src/sys/uvm/uvm_object.c:1.10
--- src/sys/uvm/uvm_object.c:1.9	Sun Jun 12 06:36:38 2011
+++ src/sys/uvm/uvm_object.c	Sat Jun 18 21:14:43 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_object.c,v 1.9 2011/06/12 06:36:38 mrg Exp $	*/
+/*	$NetBSD: uvm_object.c,v 1.10 2011/06/18 21:14:43 rmind Exp $	*/
 
 /*
  * Copyright (c) 2006, 2010 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_object.c,v 1.9 2011/06/12 06:36:38 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_object.c,v 1.10 2011/06/18 21:14:43 rmind Exp $");
 
 #include "opt_ddb.h"
 
@@ -84,10 +84,9 @@
 
 	KASSERT(rb_tree_iterate(&uo->rb_tree, NULL, RB_DIR_LEFT) == NULL);
 
-	/* Purge any UBC entries with this object. */
-	if (__predict_false(!LIST_EMPTY(&uo->uo_ubc))) {
-		ubc_purge(uo);
-	}
+	/* Purge any UBC entries associated with this object. */
+	ubc_purge(uo);
+
 	/* Destroy the lock, if requested. */
 	if (dlock) {
 		mutex_obj_free(uo->vmobjlock);

Reply via email to