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);