diff options
author | Stephan Uphoff <ups@FreeBSD.org> | 2008-05-20 19:05:43 +0000 |
---|---|---|
committer | Stephan Uphoff <ups@FreeBSD.org> | 2008-05-20 19:05:43 +0000 |
commit | 2ac78f0e1a784ff14218e3f5320f4c6269b4eb78 (patch) | |
tree | 122fb04f7bf2895af8ccd1d933a2cf8c59347db2 /sys/vm/vnode_pager.c | |
parent | c54a18d26b6afde430af32090857d70da0983532 (diff) | |
download | src-2ac78f0e1a784ff14218e3f5320f4c6269b4eb78.tar.gz src-2ac78f0e1a784ff14218e3f5320f4c6269b4eb78.zip |
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
Notes
Notes:
svn path=/head/; revision=179159
Diffstat (limited to 'sys/vm/vnode_pager.c')
-rw-r--r-- | sys/vm/vnode_pager.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 4d6cea26bd3a..40e75d9827ed 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); } |