- Move lkmnosys() to kern_syscall.c

- Have the VFS lkm support use vfs_register() etc rather than having it's
  own version.
- Have the syscall lkm support use syscall_register() etc rather than
  having it's own verison.
- Convert the lkm driver to a module.
This commit is contained in:
Peter Wemm 1999-01-17 19:00:58 +00:00
parent 46db48360d
commit 87acc0db42

View File

@ -30,11 +30,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: kern_lkm.c,v 1.58 1998/10/25 17:44:51 phk Exp $
* $Id: kern_lkm.c,v 1.59 1998/11/10 09:12:40 peter Exp $
*/
#include "opt_devfs.h"
#include "opt_no_lkm.h"
#include <sys/param.h>
#include <sys/systm.h>
@ -79,16 +78,6 @@ static int lkm_state = LKMS_IDLE;
static struct lkm_table lkmods[MAXLKMS]; /* table of loaded modules */
static struct lkm_table *curp; /* global for in-progress ops */
/*
* XXX this bloat just exands the sysctl__vfs linker set a little so that
* we can attach sysctls for VFS LKMs without expanding the linker set.
* Currently (1998/09/06), only one VFS uses sysctls, so 2 extra linker
* set slots are more than sufficient.
*/
extern struct linker_set sysctl__vfs;
SYSCTL_INT(_vfs, OID_AUTO, lkm0, CTLFLAG_RD, &lkm_v, 0, "");
SYSCTL_INT(_vfs, OID_AUTO, lkm1, CTLFLAG_RD, &lkm_v, 0, "");
static int _lkm_dev __P((struct lkm_table *lkmtp, int cmd));
static int _lkm_exec __P((struct lkm_table *lkmtp, int cmd));
static int _lkm_vfs __P((struct lkm_table *lkmtp, int cmd));
@ -491,21 +480,6 @@ lkmcioctl(dev, cmd, data, flag, p)
return (err);
}
/*
* Acts like "nosys" but can be identified in sysent for dynamic call
* number assignment for a limited number of calls.
*
* Place holder for system call slots reserved for loadable modules.
*/
int
lkmnosys(p, args)
struct proc *p;
struct nosys_args *args;
{
return(nosys(p, args));
}
int
lkmexists(lkmtp)
struct lkm_table *lkmtp;
@ -548,35 +522,16 @@ _lkm_syscall(lkmtp, cmd)
/* don't load twice! */
if (lkmexists(lkmtp))
return(EEXIST);
if ((i = args->lkm_offset) == LKM_ANON) { /* auto */
/*
* Search the table looking for a slot...
*/
for (i = 0; i < aout_sysvec.sv_size; i++)
if (aout_sysvec.sv_table[i].sy_call ==
(sy_call_t *)lkmnosys)
break; /* found it! */
/* out of allocable slots? */
if (i == aout_sysvec.sv_size) {
err = ENFILE;
break;
}
} else { /* assign */
if (i < 0 || i >= aout_sysvec.sv_size) {
err = EINVAL;
break;
}
}
/* save old */
bcopy(&aout_sysvec.sv_table[i],
&(args->lkm_oldent),
sizeof(struct sysent));
if (args->lkm_offset == LKM_ANON)
i = NO_SYSCALL;
else
i = args->lkm_offset;
/* replace with new */
bcopy(args->lkm_sysent,
&aout_sysvec.sv_table[i],
sizeof(struct sysent));
err = syscall_register(&i, args->lkm_sysent,
&(args->lkm_oldent));
if (err)
return(err);
/* done! */
args->lkm_offset = i; /* slot in sysent[] */
@ -587,11 +542,9 @@ _lkm_syscall(lkmtp, cmd)
/* current slot... */
i = args->lkm_offset;
/* replace current slot contents with old contents */
bcopy(&(args->lkm_oldent),
&aout_sysvec.sv_table[i],
sizeof(struct sysent));
err = syscall_deregister(&i, &(args->lkm_oldent));
if (err)
return(err);
break;
case LKM_E_STAT: /* no special handling... */
@ -611,11 +564,8 @@ _lkm_vfs(lkmtp, cmd)
int cmd;
{
struct lkm_vfs *args = lkmtp->private.lkm_vfs;
struct linker_set *l;
struct sysctl_oid **oidpp;
struct vfsconf *vfc = args->lkm_vfsconf;
struct vfsconf *vfsp, *prev_vfsp;
int error, i, maxtypenum;
int error, i;
switch(cmd) {
case LKM_E_LOAD:
@ -623,38 +573,13 @@ _lkm_vfs(lkmtp, cmd)
if (lkmexists(lkmtp))
return(EEXIST);
for (vfsp = vfsconf; vfsp->vfc_next; vfsp = vfsp->vfc_next) {
if (!strcmp(vfc->vfc_name, vfsp->vfc_name)) {
return EEXIST;
}
}
args->lkm_offset = vfc->vfc_typenum = maxvfsconf++;
if (vfc->vfc_vfsops->vfs_oid != NULL) {
l = &sysctl__vfs;
for (i = l->ls_length,
oidpp = (struct sysctl_oid **)l->ls_items;
i--; oidpp++) {
if (!*oidpp || *oidpp == &sysctl___vfs_lkm0 ||
*oidpp == &sysctl___vfs_lkm1) {
*oidpp = vfc->vfc_vfsops->vfs_oid;
(*oidpp)->oid_number = vfc->vfc_typenum;
sysctl_order_all();
break;
}
}
}
vfsp->vfc_next = vfc;
vfc->vfc_next = NULL;
for(i = 0; args->lkm_vnodeops->ls_items[i]; i++)
vfs_add_vnodeops((void*)args->lkm_vnodeops->ls_items[i]);
error = vfs_register(vfc);
if (error)
return(error);
/*
* Call init function for this VFS...
*/
(*(vfc->vfc_vfsops->vfs_init))(vfc);
args->lkm_offset = vfc->vfc_typenum;
/* done! */
break;
@ -663,53 +588,13 @@ _lkm_vfs(lkmtp, cmd)
/* current slot... */
i = args->lkm_offset;
prev_vfsp = NULL;
for (vfsp = vfsconf; vfsp;
prev_vfsp = vfsp, vfsp = vfsp->vfc_next) {
if (!strcmp(vfc->vfc_name, vfsp->vfc_name))
break;
}
if (vfsp == NULL) {
return EINVAL;
}
if (vfsp->vfc_refcount) {
return EBUSY;
}
if (vfc->vfc_vfsops->vfs_uninit != NULL) {
error = (*vfc->vfc_vfsops->vfs_uninit)(vfsp);
if (error)
return (error);
}
prev_vfsp->vfc_next = vfsp->vfc_next;
error = vfs_unregister(vfc);
if (error)
return(error);
for(i = 0; args->lkm_vnodeops->ls_items[i]; i++)
vfs_rm_vnodeops((void*)args->lkm_vnodeops->ls_items[i]);
if (vfsp->vfc_vfsops->vfs_oid != NULL) {
l = &sysctl__vfs;
for (i = l->ls_length,
oidpp = (struct sysctl_oid **)l->ls_items;
i--; oidpp++) {
if (*oidpp == vfsp->vfc_vfsops->vfs_oid) {
*oidpp = NULL;
sysctl_order_all();
break;
}
}
}
/*
* Maintain maxvfsconf.
*/
maxtypenum = 0;
for (vfsp = vfsconf; vfsp != NULL; vfsp = vfsp->vfc_next)
if (maxtypenum < vfsp->vfc_typenum)
maxtypenum = vfsp->vfc_typenum;
maxvfsconf = maxtypenum + 1;
break;
case LKM_E_STAT: /* no special handling... */
@ -914,27 +799,40 @@ lkm_nullcmd(lkmtp, cmd)
return (0);
}
static lkm_devsw_installed = 0;
#ifdef DEVFS
static void *lkmc_devfs_token;
#endif
static void lkm_drvinit(void *unused)
static int
lkm_modevent(module_t mod, int type, void *data)
{
dev_t dev;
static struct cdevsw *oldcdevsw;
if( ! lkm_devsw_installed ) {
switch (type) {
case MOD_LOAD:
dev = makedev(CDEV_MAJOR, 0);
cdevsw_add(&dev,&lkmc_cdevsw, NULL);
lkm_devsw_installed = 1;
cdevsw_add(&dev, &lkmc_cdevsw, &oldcdevsw);
#ifdef DEVFS
lkmc_devfs_token = devfs_add_devswf(&lkmc_cdevsw, 0, DV_CHR,
UID_ROOT, GID_WHEEL, 0644,
"lkm");
#endif
}
}
#ifndef NO_LKM
SYSINIT(lkmdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,lkm_drvinit,NULL)
break;
case MOD_UNLOAD:
#ifdef DEVFS
devfs_remove_dev(lkmc_devfs_token);
#endif
cdevsw_add(&dev, oldcdevsw, NULL);
break;
default:
break;
}
return 0;
}
static moduledata_t lkm_mod = {
"lkm",
lkm_modevent,
NULL
};
DECLARE_MODULE(lkm, lkm_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR);