aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_lkm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_lkm.c')
-rw-r--r--sys/kern/kern_lkm.c65
1 files changed, 37 insertions, 28 deletions
diff --git a/sys/kern/kern_lkm.c b/sys/kern/kern_lkm.c
index aa00040f6c90..5b48196cb58e 100644
--- a/sys/kern/kern_lkm.c
+++ b/sys/kern/kern_lkm.c
@@ -561,65 +561,74 @@ _lkm_vfs(lkmtp, cmd)
int cmd;
{
struct lkm_vfs *args = lkmtp->private.lkm_vfs;
+ struct vfsconf *vfc = args->lkm_vfsconf;
+ extern struct vfsconf void_vfsconf;
int i;
int err = 0;
-#if 0
switch(cmd) {
case LKM_E_LOAD:
/* don't load twice! */
if (lkmexists(lkmtp))
return(EEXIST);
- /* make sure there's no VFS in the table with this name */
- for (i = 0; i < nvfssw; i++)
- if (vfssw[i] != (struct vfsops *)0 &&
- strncmp(vfssw[i]->vfs_name,
- args->lkm_vfsops->vfs_name, MFSNAMELEN) == 0)
- return (EEXIST);
-
- /* pick the last available empty slot */
- for (i = nvfssw - 1; i >= 0; i--)
- if (vfssw[i] == (struct vfsops *)0)
- break;
- if (i == -1) { /* or if none, punt */
- err = EINVAL;
- break;
+ for(i = 0; i < MOUNT_MAXTYPE; i++) {
+ if(!strcmp(vfc->vfc_name, vfsconf[i]->vfc_name)) {
+ return EEXIST;
+ }
}
- /*
- * Set up file system
- */
- vfssw[i] = args->lkm_vfsops;
+ if (args->lkm_offset != vfc->vfc_index)
+ return EINVAL;
+
+ i = args->lkm_offset;
+ if (!args->lkm_offset) {
+ for (i = MOUNT_MAXTYPE - 1; i >= 0; i--) {
+ if(vfsconf[i] == &void_vfsconf)
+ break;
+ }
+ }
+ if (i < 0) {
+ return EINVAL;
+ }
+ args->lkm_offset = vfc->vfc_index = i;
+ vfsconf[i] = vfc;
+ vfssw[i] = vfc->vfc_vfsops;
+
+ /* like in vfs_op_init */
+ for(i = 0; args->lkm_vnodeops->ls_items[i]; i++) {
+ struct vnodeopv_desc *opv =
+ (struct vnodeopv_desc *)args->lkm_vnodeops->ls_items[i];
+ *(opv->opv_desc_vector_p) = NULL;
+ }
+ vfs_opv_init((struct vnodeopv_desc **)args->lkm_vnodeops->ls_items);
/*
* Call init function for this VFS...
*/
- (*(vfssw[i]->vfs_init))();
+ (*(vfssw[vfc->vfc_index]->vfs_init))();
/* done! */
args->lkm_offset = i; /* slot in vfssw[] */
break;
case LKM_E_UNLOAD:
-#ifdef notyet
/* current slot... */
i = args->lkm_offset;
+ if (vfsconf[i]->vfc_refcount) {
+ return EBUSY;
+ }
+
/* replace current slot contents with old contents */
vfssw[i] = (struct vfsops *)0;
-#else
- /* it's not safe to remove a vfs */
- err = EBUSY;
-#endif
+ vfsconf[i] = &void_vfsconf;
+
break;
case LKM_E_STAT: /* no special handling... */
break;
}
-#else
- err = EINVAL;
-#endif
return(err);
}