diff options
author | bp <bp@FreeBSD.org> | 2000-09-12 09:49:08 +0000 |
---|---|---|
committer | bp <bp@FreeBSD.org> | 2000-09-12 09:49:08 +0000 |
commit | a7bc78c86d1b25efbea8d9ad3e7354ef3a302e90 (patch) | |
tree | ae6a2a75d2b0d94e115a73fd536dca86dba92ac4 /sys/kern/vfs_default.c | |
parent | 7893328799a796677510cba9c7bbb8e52d8ce56c (diff) | |
download | FreeBSD-src-a7bc78c86d1b25efbea8d9ad3e7354ef3a302e90.zip FreeBSD-src-a7bc78c86d1b25efbea8d9ad3e7354ef3a302e90.tar.gz |
Add three new VOPs: VOP_CREATEVOBJECT, VOP_DESTROYVOBJECT and VOP_GETVOBJECT.
They will be used by nullfs and other stacked filesystems to support full
cache coherency.
Reviewed in general by: mckusick, dillon
Diffstat (limited to 'sys/kern/vfs_default.c')
-rw-r--r-- | sys/kern/vfs_default.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index e95e7e2..2b651c8 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -43,6 +43,7 @@ #include <sys/systm.h> #include <sys/bio.h> #include <sys/buf.h> +#include <sys/conf.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -51,6 +52,18 @@ #include <sys/vnode.h> #include <sys/poll.h> +#include <machine/limits.h> + +#include <vm/vm.h> +#include <vm/vm_object.h> +#include <vm/vm_extern.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> +#include <vm/vm_page.h> +#include <vm/vm_pager.h> +#include <vm/vnode_pager.h> +#include <vm/vm_zone.h> + static int vop_nostrategy __P((struct vop_strategy_args *)); /* @@ -67,7 +80,10 @@ static struct vnodeopv_entry_desc default_vnodeop_entries[] = { { &vop_advlock_desc, (vop_t *) vop_einval }, { &vop_bwrite_desc, (vop_t *) vop_stdbwrite }, { &vop_close_desc, (vop_t *) vop_null }, + { &vop_createvobject_desc, (vop_t *) vop_stdcreatevobject }, + { &vop_destroyvobject_desc, (vop_t *) vop_stddestroyvobject }, { &vop_fsync_desc, (vop_t *) vop_null }, + { &vop_getvobject_desc, (vop_t *) vop_stdgetvobject }, { &vop_inactive_desc, (vop_t *) vop_stdinactive }, { &vop_ioctl_desc, (vop_t *) vop_enotty }, { &vop_islocked_desc, (vop_t *) vop_noislocked }, @@ -522,6 +538,106 @@ vop_stdgetwritemount(ap) return (0); } +int +vop_stdcreatevobject(ap) + struct vop_createvobject_args /* { + struct vnode *vp; + struct ucred *cred; + struct proc *p; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + struct ucred *cred = ap->a_cred; + struct proc *p = ap->a_p; + struct vattr vat; + vm_object_t object; + int error = 0; + + if (!vn_isdisk(vp, NULL) && vn_canvmio(vp) == FALSE) + return (0); + +retry: + if ((object = vp->v_object) == NULL) { + if (vp->v_type == VREG || vp->v_type == VDIR) { + if ((error = VOP_GETATTR(vp, &vat, cred, p)) != 0) + goto retn; + object = vnode_pager_alloc(vp, vat.va_size, 0, 0); + } else if (devsw(vp->v_rdev) != NULL) { + /* + * This simply allocates the biggest object possible + * for a disk vnode. This should be fixed, but doesn't + * cause any problems (yet). + */ + object = vnode_pager_alloc(vp, IDX_TO_OFF(INT_MAX), 0, 0); + } else { + goto retn; + } + /* + * Dereference the reference we just created. This assumes + * that the object is associated with the vp. + */ + object->ref_count--; + vp->v_usecount--; + } else { + if (object->flags & OBJ_DEAD) { + VOP_UNLOCK(vp, 0, p); + tsleep(object, PVM, "vodead", 0); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + goto retry; + } + } + + KASSERT(vp->v_object != NULL, ("vfs_object_create: NULL object")); + vp->v_flag |= VOBJBUF; + +retn: + return (error); +} + +int +vop_stddestroyvobject(ap) + struct vop_destroyvobject_args /* { + struct vnode *vp; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + vm_object_t obj = vp->v_object; + + if (vp->v_object == NULL) + return (0); + + if (obj->ref_count == 0) { + /* + * vclean() may be called twice. The first time + * removes the primary reference to the object, + * the second time goes one further and is a + * special-case to terminate the object. + */ + vm_object_terminate(obj); + } else { + /* + * Woe to the process that tries to page now :-). + */ + vm_pager_deallocate(obj); + } + return (0); +} + +int +vop_stdgetvobject(ap) + struct vop_getvobject_args /* { + struct vnode *vp; + struct vm_object **objpp; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + struct vm_object **objpp = ap->a_objpp; + + if (objpp) + *objpp = vp->v_object; + return (vp->v_object ? 0 : EINVAL); +} + /* * vfs default ops * used to fill the vfs fucntion table to get reasonable default return values. |