Module Name:    src
Committed By:   rmind
Date:           Mon Apr 26 02:20:59 UTC 2010

Modified Files:
        src/sys/uvm [rmind-uvmplock]: uvm_bio.c uvm_extern.h uvm_object.c
            uvm_object.h

Log Message:
Add ubc_purge() and purge/deassociate any related UBC entries during
object (usually, vnode) destruction.  Since locking (and thus object)
is required to enter/remove mappings - object is not allowed anymore
to disappear with any UBC entries left.

>From original patch by ad@ with some modifications.


To generate a diff of this commit:
cvs rdiff -u -r1.68.4.3 -r1.68.4.4 src/sys/uvm/uvm_bio.c
cvs rdiff -u -r1.162.2.3 -r1.162.2.4 src/sys/uvm/uvm_extern.h
cvs rdiff -u -r1.7.4.3 -r1.7.4.4 src/sys/uvm/uvm_object.c
cvs rdiff -u -r1.26.20.1 -r1.26.20.2 src/sys/uvm/uvm_object.h

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.68.4.3 src/sys/uvm/uvm_bio.c:1.68.4.4
--- src/sys/uvm/uvm_bio.c:1.68.4.3	Sun Apr 25 22:48:26 2010
+++ src/sys/uvm/uvm_bio.c	Mon Apr 26 02:20:59 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_bio.c,v 1.68.4.3 2010/04/25 22:48:26 rmind Exp $	*/
+/*	$NetBSD: uvm_bio.c,v 1.68.4.4 2010/04/26 02:20:59 rmind Exp $	*/
 
 /*
  * Copyright (c) 1998 Chuck Silvers.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.68.4.3 2010/04/25 22:48:26 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.68.4.4 2010/04/26 02:20:59 rmind Exp $");
 
 #include "opt_uvmhist.h"
 #include "opt_ubc.h"
@@ -79,8 +79,7 @@
 #define UMAP_PAGES_LOCKED	0x0001
 #define UMAP_MAPPING_CACHED	0x0002
 
-struct ubc_map
-{
+struct ubc_map {
 	struct uvm_object *	uobj;		/* mapped object */
 	voff_t			offset;		/* offset into uobj */
 	voff_t			writeoff;	/* write offset */
@@ -91,10 +90,10 @@
 
 	LIST_ENTRY(ubc_map)	hash;		/* hash table */
 	TAILQ_ENTRY(ubc_map)	inactive;	/* inactive queue */
+	LIST_ENTRY(ubc_map)	list;		/* per-object list */
 };
 
-static struct ubc_object
-{
+static struct ubc_object {
 	struct uvm_object uobj;		/* glue for uvm_map() */
 	char *kva;			/* where ubc_object is mapped */
 	struct ubc_map *umap;		/* array of ubc_map's */
@@ -104,7 +103,6 @@
 
 	TAILQ_HEAD(ubc_inactive_head, ubc_map) *inactive;
 					/* inactive queues for ubc_map's */
-
 } ubc_object;
 
 const struct uvm_pagerops ubc_pager = {
@@ -449,8 +447,8 @@
 
 	/*
 	 * The object is already referenced, so we do not need to add a ref.
+	 * Lock order: UBC object -> ubc_map::uobj.
 	 */
-
 	mutex_enter(ubc_object.uobj.vmobjlock);
 again:
 	umap = ubc_find_mapping(uobj, umap_offset);
@@ -474,6 +472,7 @@
 
 		if (oobj != NULL) {
 			LIST_REMOVE(umap, hash);
+			LIST_REMOVE(umap, list);
 			if (umap->flags & UMAP_MAPPING_CACHED) {
 				umap->flags &= ~UMAP_MAPPING_CACHED;
 				mutex_enter(oobj->vmobjlock);
@@ -489,6 +488,7 @@
 		umap->offset = umap_offset;
 		LIST_INSERT_HEAD(&ubc_object.hash[UBC_HASH(uobj, umap_offset)],
 		    umap, hash);
+		LIST_INSERT_HEAD(&uobj->uo_ubc, umap, list);
 	} else {
 		UBC_EVCNT_INCR(wincachehit);
 		va = UBC_UMAP_ADDR(umap);
@@ -709,7 +709,6 @@
 	return error;
 }
 
-
 /*
  * uvm_vnp_zerorange:  set a range of bytes in a file to zero.
  */
@@ -737,3 +736,30 @@
 		len -= bytelen;
 	}
 }
+
+/*
+ * ubc_purge: disassociate ubc_map structures from an empty uvm_object.
+ */
+
+void
+ubc_purge(struct uvm_object *uobj)
+{
+	struct ubc_map *umap;
+	vaddr_t va;
+
+	KASSERT(uobj->uo_npages == 0);
+
+	mutex_enter(ubc_object.uobj.vmobjlock);
+	while ((umap = LIST_FIRST(&uobj->uo_ubc)) != NULL) {
+		KASSERT(umap->refcount == 0);
+		for (va = 0; va < ubc_winsize; va += PAGE_SIZE) {
+			KASSERT(!pmap_extract(pmap_kernel(),
+			    va + UBC_UMAP_ADDR(umap), NULL));
+		}
+		LIST_REMOVE(umap, list);
+		LIST_REMOVE(umap, hash);
+		umap->flags &= ~UMAP_MAPPING_CACHED;
+		umap->uobj = NULL;
+	}
+	mutex_exit(ubc_object.uobj.vmobjlock);
+}

Index: src/sys/uvm/uvm_extern.h
diff -u src/sys/uvm/uvm_extern.h:1.162.2.3 src/sys/uvm/uvm_extern.h:1.162.2.4
--- src/sys/uvm/uvm_extern.h:1.162.2.3	Fri Apr 23 21:18:00 2010
+++ src/sys/uvm/uvm_extern.h	Mon Apr 26 02:20:59 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_extern.h,v 1.162.2.3 2010/04/23 21:18:00 rmind Exp $	*/
+/*	$NetBSD: uvm_extern.h,v 1.162.2.4 2010/04/26 02:20:59 rmind Exp $	*/
 
 /*
  *
@@ -579,6 +579,7 @@
 void			ubc_release(void *, int);
 int			ubc_uiomove(struct uvm_object *, struct uio *, vsize_t,
 			    int, int);
+void			ubc_purge(struct uvm_object *);
 
 /* uvm_emap.c */
 void			uvm_emap_sysinit(void);

Index: src/sys/uvm/uvm_object.c
diff -u src/sys/uvm/uvm_object.c:1.7.4.3 src/sys/uvm/uvm_object.c:1.7.4.4
--- src/sys/uvm/uvm_object.c:1.7.4.3	Sat Apr 24 21:24:03 2010
+++ src/sys/uvm/uvm_object.c	Mon Apr 26 02:20:59 2010
@@ -1,7 +1,7 @@
-/*	$NetBSD: uvm_object.c,v 1.7.4.3 2010/04/24 21:24:03 rmind Exp $	*/
+/*	$NetBSD: uvm_object.c,v 1.7.4.4 2010/04/26 02:20:59 rmind Exp $	*/
 
 /*
- * Copyright (c) 2006 The NetBSD Foundation, Inc.
+ * Copyright (c) 2006, 2010 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_object.c,v 1.7.4.3 2010/04/24 21:24:03 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_object.c,v 1.7.4.4 2010/04/26 02:20:59 rmind Exp $");
 
 #include "opt_ddb.h"
 
@@ -49,8 +49,8 @@
 #include <uvm/uvm.h>
 #include <uvm/uvm_ddb.h>
 
-/* We will fetch this page count per step */
-#define	FETCH_PAGECOUNT	16
+/* Page count to fetch per single step. */
+#define	FETCH_PAGECOUNT			16
 
 /*
  * uvm_obj_init: initialize UVM memory object.
@@ -68,6 +68,7 @@
 	}
 	uo->pgops = ops;
 	TAILQ_INIT(&uo->memq);
+	LIST_INIT(&uo->uo_ubc);
 	uo->uo_npages = 0;
 	uo->uo_refs = refs;
 	rb_tree_init(&uo->rb_tree, &uvm_page_tree_ops);
@@ -83,6 +84,11 @@
 	void *tmp = NULL;
 	KASSERT(rb_tree_find_node_geq(&uo->rb_tree, &tmp) == NULL);
 #endif
+	/* Purge any UBC entries with this object. */
+	if (__predict_false(!LIST_EMPTY(&uo->uo_ubc))) {
+		ubc_purge(uo);
+	}
+	/* Finally, safe to destory the lock. */
 	if (lockptr) {
 		KASSERT(uo->vmobjlock == lockptr);
 		mutex_destroy(uo->vmobjlock);

Index: src/sys/uvm/uvm_object.h
diff -u src/sys/uvm/uvm_object.h:1.26.20.1 src/sys/uvm/uvm_object.h:1.26.20.2
--- src/sys/uvm/uvm_object.h:1.26.20.1	Tue Mar 16 15:38:18 2010
+++ src/sys/uvm/uvm_object.h	Mon Apr 26 02:20:59 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_object.h,v 1.26.20.1 2010/03/16 15:38:18 rmind Exp $	*/
+/*	$NetBSD: uvm_object.h,v 1.26.20.2 2010/04/26 02:20:59 rmind Exp $	*/
 
 /*
  *
@@ -41,6 +41,7 @@
  * uvm_object.h
  */
 
+#include <sys/queue.h>
 #include <sys/rb.h>
 
 /*
@@ -54,6 +55,7 @@
 	int			uo_npages;	/* # of pages in memq */
 	unsigned		uo_refs;	/* reference count */
 	struct rb_tree		rb_tree;	/* tree of pages */
+	LIST_HEAD(,ubc_map)	uo_ubc;		/* ubc mappings */
 };
 
 /*

Reply via email to