summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authorups <ups@FreeBSD.org>2008-05-20 19:05:43 +0000
committerups <ups@FreeBSD.org>2008-05-20 19:05:43 +0000
commitfbd329664f5e1e99035c0b473a42b33812b91466 (patch)
tree122fb04f7bf2895af8ccd1d933a2cf8c59347db2 /sys/vm
parent8a663465644dd0d19159348afb69bb2462822ed1 (diff)
downloadFreeBSD-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.c36
-rw-r--r--sys/vm/vm_object.h1
-rw-r--r--sys/vm/vnode_pager.c22
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);
}
OpenPOWER on IntegriCloud