diff options
author | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2010-09-10 16:34:10 +0000 |
---|---|---|
committer | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2010-09-10 16:34:10 +0000 |
commit | 924988b6ec2a9e6a026b5489028ad504451931ac (patch) | |
tree | 1b3c600d98211e262609942c2f20c60816cd46ec /sys/kern/vfs_init.c | |
parent | dc82911ae9236515748693d3963bcf4c56827fcb (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.c | 158 |
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, |