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:
parent
edfbe15080
commit
4e61198e8f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=41056
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user