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:
parent
c54a18d26b
commit
2ac78f0e1a
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user