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
This commit is contained in:
Stephan Uphoff 2008-05-20 19:05:43 +00:00
parent c54a18d26b
commit 2ac78f0e1a
4 changed files with 51 additions and 18 deletions

View File

@ -168,6 +168,16 @@ ufs_lookup(ap)
vdp = ap->a_dvp;
dp = VTOI(vdp);
/*
* Create a vm object if vmiodirenable is enabled.
* Alternatively we could call vnode_create_vobject
* in VFS_VGET but we could end up creating objects
* that are never used.
*/
vnode_create_vobject(vdp, DIP(dp, i_size), cnp->cn_thread);
/*
* We now have a segment name to search for, and a directory to search.
*

View File

@ -593,6 +593,30 @@ vm_object_deallocate(vm_object_t object)
}
}
/*
* 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);
}
/*

View File

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

View File

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