git: b730fd30b78f - main - vm: Add KPI to dynamically register pagers

Konstantin Belousov kib at FreeBSD.org
Thu May 13 17:14:17 UTC 2021


The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=b730fd30b78f502ed5dd08e5285cb2c951495d65

commit b730fd30b78f502ed5dd08e5285cb2c951495d65
Author:     Konstantin Belousov <kib at FreeBSD.org>
AuthorDate: 2021-05-07 19:06:16 +0000
Commit:     Konstantin Belousov <kib at FreeBSD.org>
CommitDate: 2021-05-13 17:12:29 +0000

    vm: Add KPI to dynamically register pagers
    
    Pager is allowed to inherit part of its implementation from the existing
    pager, which is done by copying non-NULL virtual method slots.
    
    Reviewed by:    markj
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D30168
---
 sys/vm/vm.h        |  1 +
 sys/vm/vm_object.c | 15 +++++++++-
 sys/vm/vm_object.h |  1 +
 sys/vm/vm_pager.c  | 82 +++++++++++++++++++++++++++++++++++++++++++++++-------
 sys/vm/vm_pager.h  |  3 ++
 5 files changed, 91 insertions(+), 11 deletions(-)

diff --git a/sys/vm/vm.h b/sys/vm/vm.h
index 2aae787d7f58..ca310b15b43c 100644
--- a/sys/vm/vm.h
+++ b/sys/vm/vm.h
@@ -98,6 +98,7 @@ enum obj_type {
 	OBJT_SG,
 	OBJT_MGTDEVICE,
 	OBJT_SWAP_TMPFS,
+	OBJT_FIRST_DYN,
 };
 typedef u_char objtype_t;
 
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 8cb4c0006c59..73cbdfb1ece4 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -430,7 +430,8 @@ vm_object_allocate(objtype_t type, vm_pindex_t size)
 		flags = 0;
 		break;
 	default:
-		panic("vm_object_allocate: type %d is undefined", type);
+		panic("vm_object_allocate: type %d is undefined or dynamic",
+		    type);
 	}
 	object = (vm_object_t)uma_zalloc(obj_zone, M_WAITOK);
 	_vm_object_allocate(type, size, flags, object, NULL);
@@ -438,6 +439,18 @@ vm_object_allocate(objtype_t type, vm_pindex_t size)
 	return (object);
 }
 
+vm_object_t
+vm_object_allocate_dyn(objtype_t dyntype, vm_pindex_t size, u_short flags)
+{
+	vm_object_t object;
+
+	MPASS(dyntype >= OBJT_FIRST_DYN /* && dyntype < nitems(pagertab) */);
+	object = (vm_object_t)uma_zalloc(obj_zone, M_WAITOK);
+	_vm_object_allocate(dyntype, size, flags, object, NULL);
+
+	return (object);
+}
+
 /*
  *	vm_object_allocate_anon:
  *
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
index 0e1ed321255f..7e99288e0ff2 100644
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -356,6 +356,7 @@ extern int umtx_shm_vnobj_persistent;
 vm_object_t vm_object_allocate (objtype_t, vm_pindex_t);
 vm_object_t vm_object_allocate_anon(vm_pindex_t, vm_object_t, struct ucred *,
    vm_size_t);
+vm_object_t vm_object_allocate_dyn(objtype_t, vm_pindex_t, u_short);
 boolean_t vm_object_coalesce(vm_object_t, vm_ooffset_t, vm_size_t, vm_size_t,
    boolean_t);
 void vm_object_collapse (vm_object_t);
diff --git a/sys/vm/vm_pager.c b/sys/vm/vm_pager.c
index 9476058a75bf..432a948cfe81 100644
--- a/sys/vm/vm_pager.c
+++ b/sys/vm/vm_pager.c
@@ -165,7 +165,7 @@ static const struct pagerops deadpagerops = {
 	.pgo_getvp =	dead_pager_getvp,
 };
 
-const struct pagerops *pagertab[] __read_mostly = {
+const struct pagerops *pagertab[16] __read_mostly = {
 	[OBJT_DEFAULT] =	&defaultpagerops,
 	[OBJT_SWAP] =		&swappagerops,
 	[OBJT_VNODE] =		&vnodepagerops,
@@ -176,18 +176,24 @@ const struct pagerops *pagertab[] __read_mostly = {
 	[OBJT_MGTDEVICE] = 	&mgtdevicepagerops,
 	[OBJT_SWAP_TMPFS] =	&swaptmpfspagerops,
 };
+static struct mtx pagertab_lock;
 
 void
 vm_pager_init(void)
 {
 	const struct pagerops **pgops;
+	int i;
+
+	mtx_init(&pagertab_lock, "dynpag", NULL, MTX_DEF);
 
 	/*
 	 * Initialize known pagers
 	 */
-	for (pgops = pagertab; pgops < &pagertab[nitems(pagertab)]; pgops++)
+	for (i = 0; i < OBJT_FIRST_DYN; i++) {
+		pgops = &pagertab[i];
 		if ((*pgops)->pgo_init != NULL)
 			(*(*pgops)->pgo_init)();
+	}
 }
 
 static int nswbuf_max;
@@ -245,15 +251,9 @@ vm_object_t
 vm_pager_allocate(objtype_t type, void *handle, vm_ooffset_t size,
     vm_prot_t prot, vm_ooffset_t off, struct ucred *cred)
 {
-	vm_object_t ret;
-	const struct pagerops *ops;
+	MPASS(type < nitems(pagertab));
 
-	ops = pagertab[type];
-	if (ops)
-		ret = (*ops->pgo_alloc)(handle, size, prot, off, cred);
-	else
-		ret = NULL;
-	return (ret);
+	return ((*pagertab[type]->pgo_alloc)(handle, size, prot, off, cred));
 }
 
 /*
@@ -264,6 +264,7 @@ vm_pager_deallocate(vm_object_t object)
 {
 
 	VM_OBJECT_ASSERT_WLOCKED(object);
+	MPASS(object->type < nitems(pagertab));
 	(*pagertab[object->type]->pgo_dealloc) (object);
 }
 
@@ -315,6 +316,7 @@ vm_pager_get_pages(vm_object_t object, vm_page_t *m, int count, int *rbehind,
 #endif
 	int r;
 
+	MPASS(object->type < nitems(pagertab));
 	vm_pager_assert_in(object, m, count);
 
 	r = (*pagertab[object->type]->pgo_getpages)(object, m, count, rbehind,
@@ -348,6 +350,7 @@ vm_pager_get_pages_async(vm_object_t object, vm_page_t *m, int count,
     int *rbehind, int *rahead, pgo_getpages_iodone_t iodone, void *arg)
 {
 
+	MPASS(object->type < nitems(pagertab));
 	vm_pager_assert_in(object, m, count);
 
 	return ((*pagertab[object->type]->pgo_getpages_async)(object, m,
@@ -385,6 +388,60 @@ vm_pager_object_lookup(struct pagerlst *pg_list, void *handle)
 	return (object);
 }
 
+int
+vm_pager_alloc_dyn_type(struct pagerops *ops, int base_type)
+{
+	int res;
+
+	mtx_lock(&pagertab_lock);
+	MPASS(base_type == -1 ||
+	    (base_type >= OBJT_DEFAULT && base_type < nitems(pagertab)));
+	for (res = OBJT_FIRST_DYN; res < nitems(pagertab); res++) {
+		if (pagertab[res] == NULL)
+			break;
+	}
+	if (res == nitems(pagertab)) {
+		mtx_unlock(&pagertab_lock);
+		return (-1);
+	}
+	if (base_type != -1) {
+		MPASS(pagertab[base_type] != NULL);
+#define	FIX(n)								\
+		if (ops->pgo_##n == NULL)				\
+			ops->pgo_##n = pagertab[base_type]->pgo_##n
+		FIX(init);
+		FIX(alloc);
+		FIX(dealloc);
+		FIX(getpages);
+		FIX(getpages_async);
+		FIX(putpages);
+		FIX(haspage);
+		FIX(populate);
+		FIX(pageunswapped);
+		FIX(update_writecount);
+		FIX(release_writecount);
+		FIX(set_writeable_dirty);
+		FIX(mightbedirty);
+		FIX(getvp);
+		FIX(freespace);
+#undef FIX
+	}
+	pagertab[res] = ops;	/* XXXKIB should be rel, but acq is too much */
+	mtx_unlock(&pagertab_lock);
+	return (res);
+}
+
+void
+vm_pager_free_dyn_type(objtype_t type)
+{
+	MPASS(type >= OBJT_FIRST_DYN && type < nitems(pagertab));
+
+	mtx_lock(&pagertab_lock);
+	MPASS(pagertab[type] != NULL);
+	pagertab[type] = NULL;
+	mtx_unlock(&pagertab_lock);
+}
+
 static int
 pbuf_ctor(void *mem, int size, void *arg, int flags)
 {
@@ -517,6 +574,8 @@ vm_object_set_writeable_dirty(vm_object_t object)
 {
 	pgo_set_writeable_dirty_t *method;
 
+	MPASS(object->type < nitems(pagertab));
+
 	method = pagertab[object->type]->pgo_set_writeable_dirty;
 	if (method != NULL)
 		method(object);
@@ -527,6 +586,8 @@ vm_object_mightbedirty(vm_object_t object)
 {
 	pgo_mightbedirty_t *method;
 
+	MPASS(object->type < nitems(pagertab));
+
 	method = pagertab[object->type]->pgo_mightbedirty;
 	if (method == NULL)
 		return (false);
@@ -541,6 +602,7 @@ int
 vm_object_kvme_type(vm_object_t object, struct vnode **vpp)
 {
 	VM_OBJECT_ASSERT_LOCKED(object);
+	MPASS(object->type < nitems(pagertab));
 
 	if (vpp != NULL)
 		*vpp = vm_object_vnode(object);
diff --git a/sys/vm/vm_pager.h b/sys/vm/vm_pager.h
index 5e0261f818cf..098d48ea3d9d 100644
--- a/sys/vm/vm_pager.h
+++ b/sys/vm/vm_pager.h
@@ -249,6 +249,9 @@ vm_pager_freespace(vm_object_t object, vm_pindex_t start,
 		method(object, start, size);
 }
 
+int vm_pager_alloc_dyn_type(struct pagerops *ops, int base_type);
+void vm_pager_free_dyn_type(objtype_t type);
+
 struct cdev_pager_ops {
 	int (*cdev_pg_fault)(vm_object_t vm_obj, vm_ooffset_t offset,
 	    int prot, vm_page_t *mres);


More information about the dev-commits-src-all mailing list