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