Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_pager.c
Show First 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | |||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/vnode.h> | #include <sys/vnode.h> | ||||
#include <sys/bio.h> | #include <sys/bio.h> | ||||
#include <sys/buf.h> | #include <sys/buf.h> | ||||
#include <sys/ucred.h> | #include <sys/ucred.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/rwlock.h> | #include <sys/rwlock.h> | ||||
#include <sys/user.h> | |||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/vm_param.h> | #include <vm/vm_param.h> | ||||
#include <vm/vm_kern.h> | #include <vm/vm_kern.h> | ||||
#include <vm/vm_object.h> | #include <vm/vm_object.h> | ||||
#include <vm/vm_page.h> | #include <vm/vm_page.h> | ||||
#include <vm/vm_pager.h> | #include <vm/vm_pager.h> | ||||
#include <vm/vm_extern.h> | #include <vm/vm_extern.h> | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
/* | /* | ||||
* For OBJT_DEAD objects, v_writecount was handled in | * For OBJT_DEAD objects, v_writecount was handled in | ||||
* vnode_pager_dealloc(). | * vnode_pager_dealloc(). | ||||
*/ | */ | ||||
} | } | ||||
static const struct pagerops deadpagerops = { | static const struct pagerops deadpagerops = { | ||||
.pgo_kvme_type = KVME_TYPE_DEAD, | |||||
.pgo_alloc = dead_pager_alloc, | .pgo_alloc = dead_pager_alloc, | ||||
.pgo_dealloc = dead_pager_dealloc, | .pgo_dealloc = dead_pager_dealloc, | ||||
.pgo_getpages = dead_pager_getpages, | .pgo_getpages = dead_pager_getpages, | ||||
.pgo_putpages = dead_pager_putpages, | .pgo_putpages = dead_pager_putpages, | ||||
.pgo_haspage = dead_pager_haspage, | .pgo_haspage = dead_pager_haspage, | ||||
.pgo_getvp = dead_pager_getvp, | .pgo_getvp = dead_pager_getvp, | ||||
}; | }; | ||||
const struct pagerops *pagertab[] __read_mostly = { | const struct pagerops *pagertab[16] __read_mostly = { | ||||
[OBJT_DEFAULT] = &defaultpagerops, | [OBJT_DEFAULT] = &defaultpagerops, | ||||
[OBJT_SWAP] = &swappagerops, | [OBJT_SWAP] = &swappagerops, | ||||
[OBJT_VNODE] = &vnodepagerops, | [OBJT_VNODE] = &vnodepagerops, | ||||
[OBJT_DEVICE] = &devicepagerops, | [OBJT_DEVICE] = &devicepagerops, | ||||
[OBJT_PHYS] = &physpagerops, | [OBJT_PHYS] = &physpagerops, | ||||
[OBJT_DEAD] = &deadpagerops, | [OBJT_DEAD] = &deadpagerops, | ||||
[OBJT_SG] = &sgpagerops, | [OBJT_SG] = &sgpagerops, | ||||
[OBJT_MGTDEVICE] = &mgtdevicepagerops, | [OBJT_MGTDEVICE] = &mgtdevicepagerops, | ||||
[OBJT_SWAP_TMPFS] = &swaptmpfspagerops, | |||||
}; | }; | ||||
static struct mtx pagertab_lock; | |||||
void | void | ||||
vm_pager_init(void) | vm_pager_init(void) | ||||
{ | { | ||||
const struct pagerops **pgops; | const struct pagerops **pgops; | ||||
int i; | |||||
mtx_init(&pagertab_lock, "dynpag", NULL, MTX_DEF); | |||||
/* | /* | ||||
* Initialize known pagers | * 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) | if ((*pgops)->pgo_init != NULL) | ||||
(*(*pgops)->pgo_init)(); | (*(*pgops)->pgo_init)(); | ||||
} | } | ||||
} | |||||
static int nswbuf_max; | static int nswbuf_max; | ||||
void | void | ||||
vm_pager_bufferinit(void) | vm_pager_bufferinit(void) | ||||
{ | { | ||||
/* Main zone for paging bufs. */ | /* Main zone for paging bufs. */ | ||||
Show All 40 Lines | |||||
* Allocate an instance of a pager of the given type. | * Allocate an instance of a pager of the given type. | ||||
* Size, protection and offset parameters are passed in for pagers that | * Size, protection and offset parameters are passed in for pagers that | ||||
* need to perform page-level validation (e.g. the device pager). | * need to perform page-level validation (e.g. the device pager). | ||||
*/ | */ | ||||
vm_object_t | vm_object_t | ||||
vm_pager_allocate(objtype_t type, void *handle, vm_ooffset_t size, | vm_pager_allocate(objtype_t type, void *handle, vm_ooffset_t size, | ||||
vm_prot_t prot, vm_ooffset_t off, struct ucred *cred) | vm_prot_t prot, vm_ooffset_t off, struct ucred *cred) | ||||
{ | { | ||||
vm_object_t ret; | MPASS(type < nitems(pagertab)); | ||||
const struct pagerops *ops; | |||||
ops = pagertab[type]; | return ((*pagertab[type]->pgo_alloc)(handle, size, prot, off, cred)); | ||||
if (ops) | |||||
ret = (*ops->pgo_alloc)(handle, size, prot, off, cred); | |||||
else | |||||
ret = NULL; | |||||
return (ret); | |||||
} | } | ||||
/* | /* | ||||
* The object must be locked. | * The object must be locked. | ||||
*/ | */ | ||||
void | void | ||||
vm_pager_deallocate(vm_object_t object) | vm_pager_deallocate(vm_object_t object) | ||||
{ | { | ||||
VM_OBJECT_ASSERT_WLOCKED(object); | VM_OBJECT_ASSERT_WLOCKED(object); | ||||
MPASS(object->type < nitems(pagertab)); | |||||
(*pagertab[object->type]->pgo_dealloc) (object); | (*pagertab[object->type]->pgo_dealloc) (object); | ||||
} | } | ||||
static void | static void | ||||
vm_pager_assert_in(vm_object_t object, vm_page_t *m, int count) | vm_pager_assert_in(vm_object_t object, vm_page_t *m, int count) | ||||
{ | { | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
Show All 35 Lines | |||||
vm_pager_get_pages(vm_object_t object, vm_page_t *m, int count, int *rbehind, | vm_pager_get_pages(vm_object_t object, vm_page_t *m, int count, int *rbehind, | ||||
int *rahead) | int *rahead) | ||||
{ | { | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
vm_pindex_t pindex = m[0]->pindex; | vm_pindex_t pindex = m[0]->pindex; | ||||
#endif | #endif | ||||
int r; | int r; | ||||
MPASS(object->type < nitems(pagertab)); | |||||
vm_pager_assert_in(object, m, count); | vm_pager_assert_in(object, m, count); | ||||
r = (*pagertab[object->type]->pgo_getpages)(object, m, count, rbehind, | r = (*pagertab[object->type]->pgo_getpages)(object, m, count, rbehind, | ||||
rahead); | rahead); | ||||
if (r != VM_PAGER_OK) | if (r != VM_PAGER_OK) | ||||
return (r); | return (r); | ||||
for (int i = 0; i < count; i++) { | for (int i = 0; i < count; i++) { | ||||
Show All 17 Lines | #endif | ||||
return (VM_PAGER_OK); | return (VM_PAGER_OK); | ||||
} | } | ||||
int | int | ||||
vm_pager_get_pages_async(vm_object_t object, vm_page_t *m, int count, | 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) | int *rbehind, int *rahead, pgo_getpages_iodone_t iodone, void *arg) | ||||
{ | { | ||||
MPASS(object->type < nitems(pagertab)); | |||||
vm_pager_assert_in(object, m, count); | vm_pager_assert_in(object, m, count); | ||||
return ((*pagertab[object->type]->pgo_getpages_async)(object, m, | return ((*pagertab[object->type]->pgo_getpages_async)(object, m, | ||||
count, rbehind, rahead, iodone, arg)); | count, rbehind, rahead, iodone, arg)); | ||||
} | } | ||||
/* | /* | ||||
* vm_pager_put_pages() - inline, see vm/vm_pager.h | * vm_pager_put_pages() - inline, see vm/vm_pager.h | ||||
Show All 21 Lines | if (object->handle == handle) { | ||||
break; | break; | ||||
} | } | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
} | } | ||||
} | } | ||||
return (object); | 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 | static int | ||||
pbuf_ctor(void *mem, int size, void *arg, int flags) | pbuf_ctor(void *mem, int size, void *arg, int flags) | ||||
{ | { | ||||
struct buf *bp = mem; | struct buf *bp = mem; | ||||
bp->b_vp = NULL; | bp->b_vp = NULL; | ||||
bp->b_bufobj = NULL; | bp->b_bufobj = NULL; | ||||
▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | pbrelbo(struct buf *bp) | ||||
bp->b_flags &= ~B_PAGING; | bp->b_flags &= ~B_PAGING; | ||||
} | } | ||||
void | void | ||||
vm_object_set_writeable_dirty(vm_object_t object) | vm_object_set_writeable_dirty(vm_object_t object) | ||||
{ | { | ||||
pgo_set_writeable_dirty_t *method; | pgo_set_writeable_dirty_t *method; | ||||
MPASS(object->type < nitems(pagertab)); | |||||
method = pagertab[object->type]->pgo_set_writeable_dirty; | method = pagertab[object->type]->pgo_set_writeable_dirty; | ||||
if (method != NULL) | if (method != NULL) | ||||
method(object); | method(object); | ||||
} | } | ||||
bool | bool | ||||
vm_object_mightbedirty(vm_object_t object) | vm_object_mightbedirty(vm_object_t object) | ||||
{ | { | ||||
pgo_mightbedirty_t *method; | pgo_mightbedirty_t *method; | ||||
MPASS(object->type < nitems(pagertab)); | |||||
method = pagertab[object->type]->pgo_mightbedirty; | method = pagertab[object->type]->pgo_mightbedirty; | ||||
if (method == NULL) | if (method == NULL) | ||||
return (false); | return (false); | ||||
return (method(object)); | return (method(object)); | ||||
} | |||||
/* | |||||
* Return the kvme type of the given object. | |||||
* If vpp is not NULL, set it to the object's vm_object_vnode() or NULL. | |||||
*/ | |||||
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); | |||||
return (pagertab[object->type]->pgo_kvme_type); | |||||
} | } |