diff options
author | ups <ups@FreeBSD.org> | 2008-05-20 19:05:43 +0000 |
---|---|---|
committer | ups <ups@FreeBSD.org> | 2008-05-20 19:05:43 +0000 |
commit | fbd329664f5e1e99035c0b473a42b33812b91466 (patch) | |
tree | 122fb04f7bf2895af8ccd1d933a2cf8c59347db2 /sys/vm | |
parent | 8a663465644dd0d19159348afb69bb2462822ed1 (diff) | |
download | FreeBSD-src-fbd329664f5e1e99035c0b473a42b33812b91466.zip FreeBSD-src-fbd329664f5e1e99035c0b473a42b33812b91466.tar.gz |
Allow VM object creation in ufs_lookup. (If vfs.vmiodirenable is set)
Directory IO without a VM object will store data in 'malloced' buffers
severely limiting caching of the data. Without this change VM objects for
directories are only created on an open() of the directory.
TODO: Inline test if VM object already exists to avoid locking/function call
overhead.
Tested by: kris@
Reviewed by: jeff@
Reported by: David Filo
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/vm_object.c | 36 | ||||
-rw-r--r-- | sys/vm/vm_object.h | 1 | ||||
-rw-r--r-- | sys/vm/vnode_pager.c | 22 |
3 files changed, 41 insertions, 18 deletions
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 041b289..4aed5e7 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -594,6 +594,30 @@ doterm: } /* + * vm_object_destroy removes the object from the global object list + * and frees the space for the object. + */ +void +vm_object_destroy(vm_object_t object) +{ + + /* + * Remove the object from the global object list. + */ + mtx_lock(&vm_object_list_mtx); + TAILQ_REMOVE(&vm_object_list, object, object_list); + mtx_unlock(&vm_object_list_mtx); + + /* + * Free the space for the object. + */ + uma_zfree(obj_zone, object); + +} + + + +/* * vm_object_terminate actually destroys the specified object, freeing * up all previously used resources. * @@ -674,17 +698,7 @@ vm_object_terminate(vm_object_t object) vm_pager_deallocate(object); VM_OBJECT_UNLOCK(object); - /* - * Remove the object from the global object list. - */ - mtx_lock(&vm_object_list_mtx); - TAILQ_REMOVE(&vm_object_list, object, object_list); - mtx_unlock(&vm_object_list_mtx); - - /* - * Free the space for the object. - */ - uma_zfree(obj_zone, object); + vm_object_destroy(object); } /* diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h index 4f9cad4..e6f605a 100644 --- a/sys/vm/vm_object.h +++ b/sys/vm/vm_object.h @@ -202,6 +202,7 @@ void _vm_object_allocate (objtype_t, vm_pindex_t, vm_object_t); boolean_t vm_object_coalesce(vm_object_t, vm_ooffset_t, vm_size_t, vm_size_t); void vm_object_collapse (vm_object_t); void vm_object_deallocate (vm_object_t); +void vm_object_destroy (vm_object_t); void vm_object_terminate (vm_object_t); void vm_object_set_writeable_dirty (vm_object_t); void vm_object_init (void); diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 4d6cea2..40e75d9 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -198,15 +198,14 @@ vnode_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, vp = (struct vnode *) handle; - ASSERT_VOP_ELOCKED(vp, "vnode_pager_alloc"); - /* * If the object is being terminated, wait for it to * go away. */ +retry: while ((object = vp->v_object) != NULL) { VM_OBJECT_LOCK(object); - if ((object->flags & OBJ_DEAD) == 0) + if ((object->flags & OBJ_DEAD) == 0) break; vm_object_set_flag(object, OBJ_DISCONNECTWNT); msleep(object, VM_OBJECT_MTX(object), PDROP | PVM, "vadead", 0); @@ -217,7 +216,7 @@ vnode_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, if (object == NULL) { /* - * And an object of the appropriate size + * Add an object of the appropriate size */ object = vm_object_allocate(OBJT_VNODE, OFF_TO_IDX(round_page(size))); @@ -226,11 +225,20 @@ vnode_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, object->handle = handle; if (VFS_NEEDSGIANT(vp->v_mount)) vm_object_set_flag(object, OBJ_NEEDGIANT); + VM_OBJECT_LOCK(object); + if ( vp->v_object != NULL) { + /* + * Object has been created while we were sleeping + */ + VM_OBJECT_UNLOCK(object); + vm_object_destroy(object); + goto retry; + } vp->v_object = object; - } else { + } else object->ref_count++; - VM_OBJECT_UNLOCK(object); - } + + VM_OBJECT_UNLOCK(object); vref(vp); return (object); } |