summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_default.c
diff options
context:
space:
mode:
authorbp <bp@FreeBSD.org>2000-09-12 09:49:08 +0000
committerbp <bp@FreeBSD.org>2000-09-12 09:49:08 +0000
commita7bc78c86d1b25efbea8d9ad3e7354ef3a302e90 (patch)
treeae6a2a75d2b0d94e115a73fd536dca86dba92ac4 /sys/kern/vfs_default.c
parent7893328799a796677510cba9c7bbb8e52d8ce56c (diff)
downloadFreeBSD-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.c116
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.
OpenPOWER on IntegriCloud