Make the vnode opv vector construction fully dynamic. Previously we

leaked memory on each unload and were limited to items referenced in
the kernel copy of vnode_if.c.  Now a kernel module is free to create
it's own VOP_FOO() routines and the rest of the system will happily
deal with it, including passthrough layers like union/umap/etc.

Have VFS_SET() call a common vfs_modevent() handler rather than
inline duplicating the common code all over the place.

Have VNODEOP_SET() have the vnodeops removed at unload time (assuming a
module) so that the vop_t ** vector is reclaimed.

Slightly adjust the vop_t ** vectors so that calling slot 0 is a panic
rather than a page fault.  This could happen if VOP_something() was called
without *any* handlers being present anywhere (including in vfs_default.c).
slot 1 becomes the default vector for the vnodeop table.

TODO: reclaim zones on unload (eg: nfs code)
This commit is contained in:
Peter Wemm 1998-11-10 09:04:09 +00:00
parent edfbe15080
commit 4e61198e8f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=41056
7 changed files with 258 additions and 281 deletions

View File

@ -130,6 +130,13 @@ vop_defaultop(struct vop_generic_args *ap)
return (VOCALL(default_vnodeop_p, ap->a_desc->vdesc_offset, ap));
}
int
vop_panic(struct vop_generic_args *ap)
{
panic("illegal vnode op called");
}
static int
vop_nostrategy (struct vop_strategy_args *ap)
{

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_init.c 8.3 (Berkeley) 1/4/94
* $Id: vfs_init.c,v 1.37 1998/10/25 17:44:52 phk Exp $
* $Id: vfs_init.c,v 1.38 1998/11/04 03:18:10 peter Exp $
*/
@ -49,25 +49,9 @@
#include <sys/malloc.h>
#include <vm/vm_zone.h>
static void vfs_op_init __P((void));
static void vfsinit __P((void *));
SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vfsinit, NULL)
MALLOC_DEFINE(M_VNODE, "vnodes", "Dynamically allocated vnodes");
/*
* Sigh, such primitive tools are these...
*/
#if 0
#define DODEBUG(A) A
#else
#define DODEBUG(A)
#endif
extern struct vnodeop_desc *vfs_op_descs[];
/* and the operations they perform */
/*
* XXX this bloat just exands the sysctl__vfs linker set a little so that
* we can attach sysctls for VFS modules without expanding the linker set.
@ -99,113 +83,223 @@ struct vm_zone *namei_zone;
* listing those new operations Ficus adds to NFS, all without modifying the
* NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but
* that is a(whole)nother story.) This is a feature.
*
* Without an explicit reserve area, however, you must replace vnode_if.c
* and vnode_if.h when you do this, or you will be derefrencing of the
* end of vfs_op_descs[]. This is a flaw in the use of a structure
* pointer array rather than an agregate to define vfs_op_descs. So
* it's not a very dynamic "feature".
*/
void
vfs_opv_init(struct vnodeopv_desc *opv)
/* Table of known vnodeop vectors (list of VFS vnode vectors) */
static struct vnodeopv_desc **vnodeopv_descs;
static int vnodeopv_num;
/* Table of known descs (list of vnode op handlers "vop_access_desc") */
static struct vnodeop_desc **vfs_op_descs;
static int *vfs_op_desc_refs; /* reference counts */
static int num_op_descs;
static int vfs_opv_numops;
static void
vfs_opv_recalc(void)
{
int j;
int i, j;
vop_t ***opv_desc_vector_p;
vop_t **opv_desc_vector;
struct vnodeopv_entry_desc *opve_descp;
int default_vector;
struct vnodeopv_desc *opv;
if (vfs_op_descs == NULL)
panic("vfs_opv_recalc called with null vfs_op_descs");
default_vector = VOFFSET(vop_default);
/*
* Allocate the dynamic vectors and fill them in.
* Run through and make sure all known descs have an offset
*
* vop_default_desc is hardwired at offset 1, and offset 0
* is a panic sanity check.
*/
opv_desc_vector_p = opv->opv_desc_vector_p;
vfs_opv_numops = 0;
for (i = 0; i < num_op_descs; i++)
if (vfs_opv_numops < (vfs_op_descs[i]->vdesc_offset + 1))
vfs_opv_numops = vfs_op_descs[i]->vdesc_offset + 1;
for (i = 0; i < num_op_descs; i++)
if (vfs_op_descs[i]->vdesc_offset == 0)
vfs_op_descs[i]->vdesc_offset = vfs_opv_numops++;
/*
* Allocate and init the vector, if it needs it.
* Also handle backwards compatibility.
* Allocate and fill in the vectors
*/
if (*opv_desc_vector_p == NULL) {
/* XXX - shouldn't be M_VNODE */
for (i = 0; i < vnodeopv_num; i++) {
opv = vnodeopv_descs[i];
opv_desc_vector_p = opv->opv_desc_vector_p;
if (*opv_desc_vector_p)
FREE(*opv_desc_vector_p, M_VNODE);
MALLOC(*opv_desc_vector_p, vop_t **,
vfs_opv_numops * sizeof(vop_t *), M_VNODE, M_WAITOK);
bzero(*opv_desc_vector_p,
vfs_opv_numops * sizeof(vop_t *));
DODEBUG(printf("vector at %x allocated\n",
opv_desc_vector_p));
}
opv_desc_vector = *opv_desc_vector_p;
for (j = 0; opv->opv_desc_ops[j].opve_op; j++) {
opve_descp = &(opv->opv_desc_ops[j]);
if (*opv_desc_vector_p == NULL)
panic("no memory for vop_t ** vector");
bzero(*opv_desc_vector_p, vfs_opv_numops * sizeof(vop_t *));
/*
* Sanity check: is this operation listed
* in the list of operations? We check this
* by seeing if its offest 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_offset != default_vector) {
printf("operation %s not listed in vfs_op_descs[].\n",
opve_descp->opve_op->vdesc_name);
panic ("vfs_opv_init: bad operation");
}
/*
* Fill in this entry.
*/
opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
/* Fill in, with slot 0 being panic */
opv_desc_vector = *opv_desc_vector_p;
opv_desc_vector[0] = (vop_t *)vop_panic;
for (j = 0; opv->opv_desc_ops[j].opve_op; j++) {
opve_descp = &(opv->opv_desc_ops[j]);
opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
opve_descp->opve_impl;
}
/* Replace unfilled routines with their default (slot 1). */
opv_desc_vector = *(opv->opv_desc_vector_p);
if (opv_desc_vector[1] == NULL)
panic("vfs_opv_recalc: vector without a default.");
for (j = 0; j < vfs_opv_numops; j++)
if (opv_desc_vector[j] == NULL)
opv_desc_vector[j] = opv_desc_vector[1];
}
/*
* Finally, go back and replace unfilled routines with their default.
*/
opv_desc_vector = *(opv->opv_desc_vector_p);
if (opv_desc_vector[default_vector] == NULL)
panic("vfs_opv_init: operation vector without a default.");
for (j = 0; j < vfs_opv_numops; j++)
if (opv_desc_vector[j] == NULL)
opv_desc_vector[j] = opv_desc_vector[default_vector];
}
/*
* Initialize known vnode operations vectors.
*/
static void
vfs_op_init()
void
vfs_add_vnodeops(void *data)
{
int i;
struct vnodeopv_desc *opv;
struct vnodeopv_desc **newopv;
struct vnodeop_desc **newop;
int *newref;
vop_t **opv_desc_vector;
struct vnodeop_desc *desc;
struct vnodeopv_entry_desc *opve_descp;
int i, j, k;
DODEBUG(printf("Vnode_interface_init.\n"));
DODEBUG(printf ("vfs_opv_numops=%d\n", vfs_opv_numops));
/*
* assign each op to its offset
*
* XXX This should not be needed, but is because the per
* XXX FS ops tables are not sorted according to the
* XXX vnodeop_desc's offset in vfs_op_descs. This
* XXX is the same reason we have to take the hit for
* XXX the static inline function calls instead of using
* XXX simple macro references.
*/
for (i = 0; i < vfs_opv_numops; i++)
vfs_op_descs[i]->vdesc_offset = i;
opv = (struct vnodeopv_desc *)data;
MALLOC(newopv, struct vnodeopv_desc **,
(vnodeopv_num + 1) * sizeof(*newopv), M_VNODE, M_WAITOK);
if (newopv == NULL)
panic("vfs_add_vnodeops: no memory");
if (vnodeopv_descs) {
bcopy(vnodeopv_descs, newopv, vnodeopv_num * sizeof(*newopv));
FREE(vnodeopv_descs, M_VNODE);
}
newopv[vnodeopv_num] = opv;
vnodeopv_descs = newopv;
vnodeopv_num++;
/* See if we have turned up a new vnode op desc */
opv_desc_vector = *(opv->opv_desc_vector_p);
for (i = 0; (desc = opv->opv_desc_ops[i].opve_op); i++) {
for (j = 0; j < num_op_descs; j++) {
if (desc == vfs_op_descs[j]) {
/* found it, increase reference count */
vfs_op_desc_refs[j]++;
break;
}
}
if (j == num_op_descs) {
/* not found, new entry */
MALLOC(newop, struct vnodeop_desc **,
(num_op_descs + 1) * sizeof(*newop),
M_VNODE, M_WAITOK);
if (newop == NULL)
panic("vfs_add_vnodeops: no memory for desc");
/* new reference count (for unload) */
MALLOC(newref, int *,
(num_op_descs + 1) * sizeof(*newref),
M_VNODE, M_WAITOK);
if (newref == NULL)
panic("vfs_add_vnodeops: no memory for refs");
if (vfs_op_descs) {
bcopy(vfs_op_descs, newop,
num_op_descs * sizeof(*newop));
FREE(vfs_op_descs, M_VNODE);
}
if (vfs_op_desc_refs) {
bcopy(vfs_op_desc_refs, newref,
num_op_descs * sizeof(*newref));
FREE(vfs_op_desc_refs, M_VNODE);
}
newop[num_op_descs] = desc;
newref[num_op_descs] = 1;
vfs_op_descs = newop;
vfs_op_desc_refs = newref;
num_op_descs++;
}
}
vfs_opv_recalc();
}
void
vfs_rm_vnodeops(void *data)
{
struct vnodeopv_desc *opv;
struct vnodeopv_desc **newopv;
struct vnodeop_desc **newop;
int *newref;
vop_t **opv_desc_vector;
struct vnodeop_desc *desc;
struct vnodeopv_entry_desc *opve_descp;
int i, j, k;
opv = (struct vnodeopv_desc *)data;
/* Lower ref counts on descs in the table and release if zero */
opv_desc_vector = *(opv->opv_desc_vector_p);
for (i = 0; (desc = opv->opv_desc_ops[i].opve_op); i++) {
for (j = 0; j < num_op_descs; j++) {
if (desc == vfs_op_descs[j]) {
/* found it, decrease reference count */
vfs_op_desc_refs[j]--;
break;
}
}
for (j = 0; j < num_op_descs; j++) {
if (vfs_op_desc_refs[j] > 0)
continue;
if (vfs_op_desc_refs[j] < 0)
panic("vfs_remove_vnodeops: negative refcnt");
MALLOC(newop, struct vnodeop_desc **,
(num_op_descs - 1) * sizeof(*newop),
M_VNODE, M_WAITOK);
if (newop == NULL)
panic("vfs_remove_vnodeops: no memory for desc");
/* new reference count (for unload) */
MALLOC(newref, int *,
(num_op_descs - 1) * sizeof(*newref),
M_VNODE, M_WAITOK);
if (newref == NULL)
panic("vfs_remove_vnodeops: no memory for refs");
for (k = j; k < (num_op_descs - 1); k++) {
vfs_op_descs[k] = vfs_op_descs[k + 1];
vfs_op_desc_refs[k] = vfs_op_desc_refs[k + 1];
}
bcopy(vfs_op_descs, newop,
(num_op_descs - 1) * sizeof(*newop));
bcopy(vfs_op_desc_refs, newref,
(num_op_descs - 1) * sizeof(*newref));
FREE(vfs_op_descs, M_VNODE);
FREE(vfs_op_desc_refs, M_VNODE);
vfs_op_descs = newop;
vfs_op_desc_refs = newref;
num_op_descs--;
}
}
for (i = 0; i < vnodeopv_num; i++) {
if (vnodeopv_descs[i] == opv) {
for (j = i; j < (vnodeopv_num - 1); j++)
vnodeopv_descs[j] = vnodeopv_descs[j + 1];
break;
}
}
if (i == vnodeopv_num)
panic("vfs_remove_vnodeops: opv not found");
MALLOC(newopv, struct vnodeopv_desc **,
(vnodeopv_num - 1) * sizeof(*newopv), M_VNODE, M_WAITOK);
if (newopv == NULL)
panic("vfs_remove_vnodeops: no memory");
bcopy(vnodeopv_descs, newopv, (vnodeopv_num - 1) * sizeof(*newopv));
FREE(vnodeopv_descs, M_VNODE);
vnodeopv_descs = newopv;
vnodeopv_num--;
vfs_opv_recalc();
}
/*
* Routines having to do with the management of the vnode table.
*/
extern struct vnodeops dead_vnodeops;
extern struct vnodeops spec_vnodeops;
struct vattr va_null;
/*
@ -213,8 +307,7 @@ struct vattr va_null;
*/
/* ARGSUSED*/
static void
vfsinit(dummy)
void *dummy;
vfsinit(void *dummy)
{
namei_zone = zinit("NAMEI", MAXPATHLEN, 0, 0, 2);
@ -227,10 +320,6 @@ vfsinit(dummy)
* Initialize the vnode name cache
*/
nchinit();
/*
* Build vnode operation vectors.
*/
vfs_op_init();
/*
* Initialize each file system type.
* Vfs type numbers must be distinct from VFS_GENERIC (and VFS_VFSCONF).
@ -238,10 +327,10 @@ vfsinit(dummy)
vattr_null(&va_null);
maxvfsconf = VFS_GENERIC + 1;
}
SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vfsinit, NULL)
int
vfs_register(vfc)
struct vfsconf *vfc;
vfs_register(struct vfsconf *vfc)
{
struct linker_set *l;
struct sysctl_oid **oidpp;
@ -300,25 +389,8 @@ vfs_register(vfc)
}
/*
* To be called at SI_SUB_VFS, SECOND, for each VFS before any are registered.
*/
void
vfs_mod_opv_init(handle)
void *handle;
{
struct vnodeopv_desc *opv;
opv = (struct vnodeopv_desc *)handle;
*(opv->opv_desc_vector_p) = NULL;
/* XXX there is a memory leak on unload here */
vfs_opv_init(opv);
}
int
vfs_unregister(vfc)
struct vfsconf *vfc;
vfs_unregister(struct vfsconf *vfc)
{
struct linker_set *l;
struct sysctl_oid **oidpp;
@ -365,3 +437,29 @@ vfs_unregister(vfc)
maxvfsconf = maxtypenum + 1;
return 0;
}
int
vfs_modevent(module_t mod, modeventtype_t type, void *data)
{
struct vfsconf *vfc;
struct vnodeopv_desc *opv;
int i;
int error = 0;
vfc = (struct vfsconf *)data;
switch (type) {
case MOD_LOAD:
if (vfc)
error = vfs_register(vfc);
break;
case MOD_UNLOAD:
if (vfc)
error = vfs_unregister(vfc);
break;
default: /* including MOD_SHUTDOWN */
break;
}
return (error);
}

View File

@ -32,7 +32,7 @@
# SUCH DAMAGE.
#
# @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93
# $Id: vnode_if.sh,v 1.14 1997/12/19 23:25:16 bde Exp $
# $Id: vnode_if.sh,v 1.15 1998/07/04 20:45:32 julian Exp $
#
# Script to produce VFS front-end sugar.
@ -188,7 +188,7 @@ cat << END_OF_LEADING_COMMENT > $CFILE
#include <sys/vnode.h>
struct vnodeop_desc vop_default_desc = {
0,
1, /* special case, vop_default => 1 */
"default",
0,
NULL,
@ -400,39 +400,3 @@ struct vnodeop_desc vop_bwrite_desc = {
NULL,
};
END_OF_SPECIAL_CASES
# Add the vfs_op_descs array to the C file.
$AWK '
BEGIN {
printf("\nstruct vnodeop_desc *vfs_op_descs[] = {\n");
printf("\t&vop_default_desc, /* MUST BE FIRST */\n");
printf("\t&vop_strategy_desc, /* XXX: SPECIAL CASE */\n");
printf("\t&vop_bwrite_desc, /* XXX: SPECIAL CASE */\n");
}
END {
printf("\tNULL\n};\n");
}
NF == 0 || $0 ~ "^#" {
next;
}
{
# Get the function name.
printf("\t&%s_desc,\n", $1);
# Skip the function arguments.
for (;;) {
if (getline <= 0)
exit
if ($0 ~ "^};")
break;
}
}' < $SRC >> $CFILE
cat << END_OF_NUMOPS_CODE >> $CFILE
/*
* the -1 is to account for the NULL
* XXX is the NULL still necessary? I don't think so...
*/
int vfs_opv_numops = (sizeof(vfs_op_descs)/sizeof(struct vnodeop_desc *)) - 1;
END_OF_NUMOPS_CODE

View File

@ -32,7 +32,7 @@
# SUCH DAMAGE.
#
# @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93
# $Id: vnode_if.sh,v 1.14 1997/12/19 23:25:16 bde Exp $
# $Id: vnode_if.sh,v 1.15 1998/07/04 20:45:32 julian Exp $
#
# Script to produce VFS front-end sugar.
@ -188,7 +188,7 @@ cat << END_OF_LEADING_COMMENT > $CFILE
#include <sys/vnode.h>
struct vnodeop_desc vop_default_desc = {
0,
1, /* special case, vop_default => 1 */
"default",
0,
NULL,
@ -400,39 +400,3 @@ struct vnodeop_desc vop_bwrite_desc = {
NULL,
};
END_OF_SPECIAL_CASES
# Add the vfs_op_descs array to the C file.
$AWK '
BEGIN {
printf("\nstruct vnodeop_desc *vfs_op_descs[] = {\n");
printf("\t&vop_default_desc, /* MUST BE FIRST */\n");
printf("\t&vop_strategy_desc, /* XXX: SPECIAL CASE */\n");
printf("\t&vop_bwrite_desc, /* XXX: SPECIAL CASE */\n");
}
END {
printf("\tNULL\n};\n");
}
NF == 0 || $0 ~ "^#" {
next;
}
{
# Get the function name.
printf("\t&%s_desc,\n", $1);
# Skip the function arguments.
for (;;) {
if (getline <= 0)
exit
if ($0 ~ "^};")
break;
}
}' < $SRC >> $CFILE
cat << END_OF_NUMOPS_CODE >> $CFILE
/*
* the -1 is to account for the NULL
* XXX is the NULL still necessary? I don't think so...
*/
int vfs_opv_numops = (sizeof(vfs_op_descs)/sizeof(struct vnodeop_desc *)) - 1;
END_OF_NUMOPS_CODE

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)mount.h 8.21 (Berkeley) 5/20/95
* $Id: mount.h,v 1.70 1998/11/06 16:36:31 peter Exp $
* $Id: mount.h,v 1.71 1998/11/07 04:51:36 peter Exp $
*/
#ifndef _SYS_MOUNT_H_
@ -351,47 +351,24 @@ struct vfsops {
#else
#include <sys/module.h>
#define VFS_SET(vfsops, fsname, flags) \
static struct vfsconf fsname ## _vfsconf = { \
&vfsops, \
#fsname, \
-1, \
0, \
flags | VFCF_STATIC, \
}; \
static int fsname ## _modevent(module_t mod, modeventtype_t type, \
void *data) \
{ \
struct vfsconf *vfc = (struct vfsconf *)data; \
int error = 0; \
switch (type) { \
case MOD_LOAD: \
/* printf(#fsname " module load\n"); */ \
error = vfs_register(vfc); \
if (error) \
printf(#fsname " register failed\n"); \
break; \
case MOD_UNLOAD: \
/* printf(#fsname " module unload\n"); */ \
error = vfs_unregister(vfc); \
if (error) \
printf(#fsname " register failed\n"); \
break; \
} \
return error; \
} \
static moduledata_t fsname ## _mod = { \
#fsname, \
fsname ## _modevent, \
& fsname ## _vfsconf \
}; \
static struct vfsconf fsname ## _vfsconf = { \
&vfsops, \
#fsname, \
-1, \
0, \
flags \
}; \
static moduledata_t fsname ## _mod = { \
#fsname, \
vfs_modevent, \
& fsname ## _vfsconf \
}; \
DECLARE_MODULE(fsname, fsname ## _mod, SI_SUB_VFS, SI_ORDER_MIDDLE)
#endif /* VFS_LKM */
#endif /* KERNEL */
#ifdef KERNEL
#include <net/radix.h>
#define AF_MAX 31 /* XXX */
@ -438,6 +415,7 @@ void vfs_unbusy __P((struct mount *, struct proc *));
void vfs_unmountall __P((void));
int vfs_register __P((struct vfsconf *));
int vfs_unregister __P((struct vfsconf *));
int vfs_modevent __P((module_t, modeventtype_t, void *));
extern CIRCLEQ_HEAD(mntlist, mount) mountlist; /* mounted filesystem list */
extern struct simplelock mountlist_slock;
extern struct nfs_public nfs_pub;

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)vnode.h 8.7 (Berkeley) 2/4/94
* $Id: vnode.h,v 1.76 1998/10/29 09:51:28 peter Exp $
* $Id: vnode.h,v 1.77 1998/10/31 14:05:11 peter Exp $
*/
#ifndef _SYS_VNODE_H_
@ -259,7 +259,8 @@ extern int vttoif_tab[];
#define VNODEOP_SET(f) DATA_SET(MODVNOPS,f)
#else
#define VNODEOP_SET(f) \
SYSINIT(f##init, SI_SUB_VFS, SI_ORDER_SECOND, vfs_mod_opv_init, &f);
SYSINIT(f##init, SI_SUB_VFS, SI_ORDER_SECOND, vfs_add_vnodeops, &f); \
SYSUNINIT(f##uninit, SI_SUB_VFS, SI_ORDER_SECOND, vfs_rm_vnodeops, &f);
#endif
/*
@ -487,8 +488,8 @@ void vattr_null __P((struct vattr *vap));
int vcount __P((struct vnode *vp));
void vdrop __P((struct vnode *));
int vfinddev __P((dev_t dev, enum vtype type, struct vnode **vpp));
void vfs_opv_init __P((struct vnodeopv_desc *opv));
void vfs_mod_opv_init __P((void *handle));
void vfs_add_vnodeops __P((void *));
void vfs_rm_vnodeops __P((void *));
int vflush __P((struct mount *mp, struct vnode *skipvp, int flags));
int vget __P((struct vnode *vp, int lockflag, struct proc *p));
void vgone __P((struct vnode *vp));
@ -535,6 +536,7 @@ int vop_einval __P((struct vop_generic_args *ap));
int vop_enotty __P((struct vop_generic_args *ap));
int vop_defaultop __P((struct vop_generic_args *ap));
int vop_null __P((struct vop_generic_args *ap));
int vop_panic __P((struct vop_generic_args *ap));
struct vnode *
checkalias __P((struct vnode *vp, dev_t nvp_rdev, struct mount *mp));

View File

@ -32,7 +32,7 @@
# SUCH DAMAGE.
#
# @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93
# $Id: vnode_if.sh,v 1.14 1997/12/19 23:25:16 bde Exp $
# $Id: vnode_if.sh,v 1.15 1998/07/04 20:45:32 julian Exp $
#
# Script to produce VFS front-end sugar.
@ -188,7 +188,7 @@ cat << END_OF_LEADING_COMMENT > $CFILE
#include <sys/vnode.h>
struct vnodeop_desc vop_default_desc = {
0,
1, /* special case, vop_default => 1 */
"default",
0,
NULL,
@ -400,39 +400,3 @@ struct vnodeop_desc vop_bwrite_desc = {
NULL,
};
END_OF_SPECIAL_CASES
# Add the vfs_op_descs array to the C file.
$AWK '
BEGIN {
printf("\nstruct vnodeop_desc *vfs_op_descs[] = {\n");
printf("\t&vop_default_desc, /* MUST BE FIRST */\n");
printf("\t&vop_strategy_desc, /* XXX: SPECIAL CASE */\n");
printf("\t&vop_bwrite_desc, /* XXX: SPECIAL CASE */\n");
}
END {
printf("\tNULL\n};\n");
}
NF == 0 || $0 ~ "^#" {
next;
}
{
# Get the function name.
printf("\t&%s_desc,\n", $1);
# Skip the function arguments.
for (;;) {
if (getline <= 0)
exit
if ($0 ~ "^};")
break;
}
}' < $SRC >> $CFILE
cat << END_OF_NUMOPS_CODE >> $CFILE
/*
* the -1 is to account for the NULL
* XXX is the NULL still necessary? I don't think so...
*/
int vfs_opv_numops = (sizeof(vfs_op_descs)/sizeof(struct vnodeop_desc *)) - 1;
END_OF_NUMOPS_CODE