summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_init.c
diff options
context:
space:
mode:
authorThordur I. Bjornsson <thib@cvs.openbsd.org>2010-09-10 16:34:10 +0000
committerThordur I. Bjornsson <thib@cvs.openbsd.org>2010-09-10 16:34:10 +0000
commit924988b6ec2a9e6a026b5489028ad504451931ac (patch)
tree1b3c600d98211e262609942c2f20c60816cd46ec /sys/kern/vfs_init.c
parentdc82911ae9236515748693d3963bcf4c56827fcb (diff)
Backout the VOP diff until the issues naddy was seeing on alpha (gcc3)
have been resolved.
Diffstat (limited to 'sys/kern/vfs_init.c')
-rw-r--r--sys/kern/vfs_init.c158
1 files changed, 153 insertions, 5 deletions
diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c
index 34680ef087a..c44cace347e 100644
--- a/sys/kern/vfs_init.c
+++ b/sys/kern/vfs_init.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_init.c,v 1.26 2010/09/06 23:44:10 thib Exp $ */
+/* $OpenBSD: vfs_init.c,v 1.27 2010/09/10 16:34:08 thib Exp $ */
/* $NetBSD: vfs_init.c,v 1.6 1996/02/09 19:00:58 christos Exp $ */
/*
@@ -50,9 +50,150 @@
#include <sys/pool.h>
#include <sys/systm.h>
+/* a list of lists of vnodeops defns */
+extern struct vnodeopv_desc *vfs_opv_descs[];
+
+/* and the operations they perform */
+extern struct vnodeop_desc *vfs_op_descs[];
+
struct pool namei_pool;
-/* Initialize the vnode structures and initialize each file system type. */
+/*
+ * This code doesn't work if the defn is **vnodop_defns with cc.
+ * The problem is because of the compiler sometimes putting in an
+ * extra level of indirection for arrays. It's an interesting
+ * "feature" of C.
+ */
+int vfs_opv_numops;
+
+typedef int (*PFI)(void *);
+
+/*
+ * vfs_init.c
+ *
+ * Allocate and fill in operations vectors.
+ *
+ * An undocumented feature of this approach to defining operations is that
+ * there can be multiple entries in vfs_opv_descs for the same operations
+ * vector. This allows third parties to extend the set of operations
+ * supported by another layer in a binary compatible way. For example,
+ * assume that NFS needed to be modified to support Ficus. NFS has an entry
+ * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by
+ * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions)
+ * listing those new operations Ficus adds to NFS, all without modifying the
+ * NFS code. (Of course, the OTW NFS protocol still needs to be munged, but
+ * that is a(whole)nother story.) This is a feature.
+ */
+
+/*
+ * Allocate and init the vector, if it needs it.
+ * Also handle backwards compatibility.
+ */
+void
+vfs_opv_init_explicit(struct vnodeopv_desc *vfs_opv_desc)
+{
+ int (**opv_desc_vector)(void *);
+ struct vnodeopv_entry_desc *opve_descp;
+
+ opv_desc_vector = *(vfs_opv_desc->opv_desc_vector_p);
+
+ if (opv_desc_vector == NULL) {
+ /* XXX - shouldn't be M_VNODE */
+ opv_desc_vector = malloc(vfs_opv_numops * sizeof(PFI),
+ M_VNODE, M_WAITOK|M_ZERO);
+ *(vfs_opv_desc->opv_desc_vector_p) = opv_desc_vector;
+ }
+
+ for (opve_descp = vfs_opv_desc->opv_desc_ops;
+ opve_descp->opve_op; opve_descp++) {
+ /*
+ * Sanity check: is this operation listed
+ * in the list of operations? We check this
+ * by seeing if its offset is zero. Since
+ * the default routine should always be listed
+ * first, it should be the only one with a zero
+ * offset. Any other operation with a zero
+ * offset is probably not listed in
+ * vfs_op_descs, and so is probably an error.
+ *
+ * A panic here means the layer programmer
+ * has committed the all-too common bug
+ * of adding a new operation to the layer's
+ * list of vnode operations but
+ * not adding the operation to the system-wide
+ * list of supported operations.
+ */
+ if (opve_descp->opve_op->vdesc_offset == 0 &&
+ opve_descp->opve_op != VDESC(vop_default)) {
+ printf("operation %s not listed in %s.\n",
+ opve_descp->opve_op->vdesc_name, "vfs_op_descs");
+ panic ("vfs_opv_init: bad operation");
+ }
+
+ /*
+ * Fill in this entry.
+ */
+ opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
+ opve_descp->opve_impl;
+ }
+}
+
+void
+vfs_opv_init_default(struct vnodeopv_desc *vfs_opv_desc)
+{
+ int j;
+ int (**opv_desc_vector)(void *);
+
+ opv_desc_vector = *(vfs_opv_desc->opv_desc_vector_p);
+
+ /*
+ * Force every operations vector to have a default routine.
+ */
+ if (opv_desc_vector[VOFFSET(vop_default)] == NULL)
+ panic("vfs_opv_init: operation vector without default routine.");
+
+ for (j = 0; j < vfs_opv_numops; j++)
+ if (opv_desc_vector[j] == NULL)
+ opv_desc_vector[j] =
+ opv_desc_vector[VOFFSET(vop_default)];
+}
+
+/* Initialize known vnode operations vectors. */
+void
+vfs_op_init(void)
+{
+ int i;
+
+ /* Set all vnode vectors to a well known value. */
+ for (i = 0; vfs_opv_descs[i]; i++)
+ *(vfs_opv_descs[i]->opv_desc_vector_p) = NULL;
+
+ /*
+ * Figure out how many ops there are by counting the table,
+ * and assign each its offset.
+ */
+ for (vfs_opv_numops = 0, i = 0; vfs_op_descs[i]; i++) {
+ vfs_op_descs[i]->vdesc_offset = vfs_opv_numops;
+ vfs_opv_numops++;
+ }
+
+ /* Allocate the dynamic vectors and fill them in. */
+ for (i = 0; vfs_opv_descs[i]; i++)
+ vfs_opv_init_explicit(vfs_opv_descs[i]);
+
+ /*
+ * Finally, go back and replace unfilled routines
+ * with their default.
+ */
+ for (i = 0; vfs_opv_descs[i]; i++)
+ vfs_opv_init_default(vfs_opv_descs[i]);
+
+}
+
+
+/*
+ * Initialize the vnode structures and initialize each file system type.
+ */
void
vfsinit(void)
{
@@ -63,11 +204,18 @@ vfsinit(void)
pool_init(&namei_pool, MAXPATHLEN, 0, 0, 0, "namei",
&pool_allocator_nointr);
- /* Initialize the vnode table. */
+ /*
+ * Initialize the vnode table
+ */
vntblinit();
-
- /* Initialize the vnode name cache. */
+ /*
+ * Initialize the vnode name cache
+ */
nchinit();
+ /*
+ * Build vnode operation vectors.
+ */
+ vfs_op_init();
/*
* Stop using vfsconf and maxvfsconf as a temporary storage,