Annotation of Net2/kern/kern_lkm.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * kern_lkm.c
        !             3:  *
        !             4:  * functions and pseudo-device for loadable kernel modules
        !             5:  *
        !             6:  * 05 Jun 93   Terry Lambert           Release cleanup
        !             7:  * 10 Feb 93   Terry Lambert           Original
        !             8:  *
        !             9:  * Copyright (c) 1992 Terrence R. Lambert.
        !            10:  * All rights reserved.
        !            11:  *
        !            12:  * Redistribution and use in source and binary forms, with or without
        !            13:  * modification, are permitted provided that the following conditions
        !            14:  * are met:
        !            15:  * 1. Redistributions of source code must retain the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer.
        !            17:  * 2. Redistributions in binary form must reproduce the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer in the
        !            19:  *    documentation and/or other materials provided with the distribution.
        !            20:  * 3. All advertising materials mentioning features or use of this software
        !            21:  *    must display the following acknowledgement:
        !            22:  *      This product includes software developed by Terrence R. Lambert.
        !            23:  * 4. The name Terrence R. Lambert may not be used to endorse or promote
        !            24:  *    products derived from this software without specific prior written
        !            25:  *    permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
        !            28:  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            29:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            30:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
        !            31:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            32:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            33:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            34:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            35:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            36:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            37:  * SUCH DAMAGE.
        !            38:  *
        !            39:  *     kern_lkm.c,v 1.3.2.1 1993/07/22 13:01:55 cgd Exp
        !            40:  */
        !            41: 
        !            42: #include "param.h"
        !            43: #include "systm.h"
        !            44: #include "ioctl.h"
        !            45: #include "tty.h"
        !            46: #include "conf.h"
        !            47: #include "file.h"
        !            48: #include "proc.h"
        !            49: #include "uio.h"
        !            50: #include "kernel.h"
        !            51: #include "vnode.h"
        !            52: #include "malloc.h"
        !            53: #include "vm/vm.h"
        !            54: #include "vm/vm_param.h"
        !            55: #include "vm/vm_kern.h"
        !            56: #include "mount.h"
        !            57: #include "exec.h"
        !            58: #include "lkm.h"
        !            59: 
        !            60: #define PAGESIZE 1024          /* kmem_alloc() allocation quantum*/
        !            61: 
        !            62: #define        LKM_ALLOC       0x01
        !            63: #define        LKM_WANT        0x02
        !            64: 
        !            65: 
        !            66: #define        LKMS_IDLE       0x00
        !            67: #define        LKMS_RESERVED   0x01
        !            68: #define        LKMS_LOADING    0x02
        !            69: #define        LKMS_LOADED     0x04
        !            70: #define        LKMS_UNLOADING  0x08
        !            71: 
        !            72: static int     lkm_v = 0;
        !            73: static int     lkm_state = LKMS_IDLE;
        !            74: 
        !            75: #ifndef MAXLKMS
        !            76: #define        MAXLKMS         20
        !            77: #endif
        !            78: 
        !            79: static struct lkm_table        lkmods[ MAXLKMS];       /* table of loaded modules*/
        !            80: static struct lkm_table        *curp;                  /* global for in-progress ops*/
        !            81: 
        !            82: /*ARGSUSED*/
        !            83: lkmopen( dev, flag, devtype, p)
        !            84: dev_t          dev;
        !            85: int            flag;
        !            86: int            devtype;
        !            87: struct proc    *p;
        !            88: {
        !            89:        int     error;
        !            90: 
        !            91:        if( minor( dev) != 0)
        !            92:                return( ENXIO);         /* bad minor #*/
        !            93: 
        !            94:        /*
        !            95:         * Use of the loadable kernel module device must be exclusive; we
        !            96:         * may try to remove this restriction later, but it's really no
        !            97:         * hardship.
        !            98:         */
        !            99:        while( lkm_v & LKM_ALLOC) {
        !           100:                if( flag & FNONBLOCK)           /* don't hang*/
        !           101:                        return( EBUSY);
        !           102:                lkm_v |= LKM_WANT;
        !           103:                /*
        !           104:                 * Sleep pending unlock; we use tsleep() to allow
        !           105:                 * an alarm out of the open.
        !           106:                 */
        !           107:                if( error = tsleep( (caddr_t)&lkm_v, TTIPRI|PCATCH, "LKM", 0))
        !           108:                        return( error); /* leave LKM_WANT set -- no problem*/
        !           109:        }
        !           110:        lkm_v |= LKM_ALLOC;
        !           111: 
        !           112:        return( 0);             /* pseudo-device open*/
        !           113: }
        !           114: 
        !           115: 
        !           116: /*
        !           117:  * l k m u n r e s e r v e
        !           118:  *
        !           119:  * Unreserve the memory associated with the current loaded module; done on
        !           120:  * a coerced close of the lkm device (close on premature exit of modload)
        !           121:  * or explicitly by modload as a result of a link failure.
        !           122:  */
        !           123: static int
        !           124: lkmunreserve()
        !           125: {
        !           126:        if( lkm_state == LKMS_IDLE)
        !           127:                return;
        !           128: 
        !           129:        /*
        !           130:         * Actually unreserve the memory
        !           131:         */
        !           132:        kmem_free( kmem_map, curp->area, curp->size);/**/
        !           133: 
        !           134:        lkm_state = LKMS_IDLE;
        !           135: }
        !           136: 
        !           137: 
        !           138: lkmclose( dev, flag, mode, p)
        !           139: dev_t          dev;
        !           140: int            flag;
        !           141: int            mode;
        !           142: struct proc    *p;
        !           143: {
        !           144:        if( !( lkm_v & LKM_ALLOC)) {
        !           145: #ifdef DEBUG
        !           146:                printf( "LKM: close before open!\n");
        !           147: #endif /* DEBUG*/
        !           148:                return( EBADF);
        !           149:        }
        !           150: 
        !           151:        /* do this before waking the herd...*/
        !           152:        if( !curp->used) {
        !           153:                /*
        !           154:                 * If we close before setting used, we have aborted
        !           155:                 * by way of error or by way of close-on-exit from
        !           156:                 * a premature exit of "modload".
        !           157:                 */
        !           158:                lkmunreserve(); /* coerce state to LKM_IDLE*/
        !           159:        }
        !           160: 
        !           161:        lkm_v &= ~LKM_ALLOC;
        !           162:        wakeup( (caddr_t)&lkm_v);       /* thundering herd "problem" here*/
        !           163: 
        !           164:        return( 0);             /* pseudo-device closed*/
        !           165: }
        !           166: 
        !           167: 
        !           168: /*ARGSUSED*/
        !           169: lkmioctl( dev, cmd, data, flag)
        !           170: dev_t          dev;
        !           171: int            cmd;
        !           172: caddr_t                data;
        !           173: int            flag;
        !           174: {
        !           175:        int                     err = 0;
        !           176:        int                     i;
        !           177:        struct lmc_resrv        *resrvp;
        !           178:        struct lmc_loadbuf      *loadbufp;
        !           179:        struct lmc_unload       *unloadp;
        !           180:        struct lmc_stat         *statp;
        !           181:        int                     (*funcp)();
        !           182:        char                    istr[ MAXLKMNAME];
        !           183: 
        !           184:        switch( cmd) {
        !           185:        case LMRESERV:          /* reserve pages for a module*/
        !           186:                if ((flag & FWRITE) == 0) /* only allow this if writing */
        !           187:                        return EPERM;
        !           188: 
        !           189:                resrvp = (struct lmc_resrv *)data;
        !           190: 
        !           191:                /*
        !           192:                 * Find a free slot.
        !           193:                 */
        !           194:                for( i = 0; i < MAXLKMS; i++) {
        !           195:                        if( !lkmods[ i].used)
        !           196:                                break;
        !           197:                }
        !           198:                if( i == MAXLKMS) {
        !           199:                        err = ENOMEM;           /* no slots available*/
        !           200:                        break;
        !           201:                }
        !           202:                curp = &lkmods[ i];
        !           203:                curp->id = i;           /* self reference slot offset*/
        !           204: 
        !           205:                resrvp->slot = i;               /* return slot*/
        !           206: 
        !           207:                /*
        !           208:                 * Get memory for module
        !           209:                 */
        !           210:                curp->size = resrvp->size;
        !           211: 
        !           212:                curp->area = (char *)kmem_alloc( kmem_map, curp->size);/**/
        !           213: 
        !           214:                curp->offset = 0;               /* load offset*/
        !           215: 
        !           216:                resrvp->addr = (unsigned long)curp->area; /* ret kernel addr*/
        !           217: 
        !           218: #ifdef DEBUG
        !           219:                printf( "LKM: LMRESERV (actual   = 0x%08x)\n", curp->area);
        !           220:                printf( "LKM: LMRESERV (adjusted = 0x%08x)\n",
        !           221:                        trunc_page(curp->area));
        !           222: #endif /* DEBUG*/
        !           223:                lkm_state = LKMS_RESERVED;
        !           224:                break;
        !           225: 
        !           226:        case LMLOADBUF:         /* Copy in; stateful, follows LMRESERV*/
        !           227:                if ((flag & FWRITE) == 0) /* only allow this if writing */
        !           228:                        return EPERM;
        !           229: 
        !           230:                loadbufp = (struct lmc_loadbuf *)data;
        !           231:                if( lkm_state != LKMS_RESERVED && lkm_state != LKMS_LOADING) {
        !           232:                        err = ENOMEM;
        !           233:                        break;
        !           234:                }
        !           235: 
        !           236:                /* account for odd size (non-page multiple) copyin*/
        !           237:                i = MIN( curp->size - curp->offset, MODIOBUF);
        !           238: 
        !           239:                /* copy in buffer full of data*/
        !           240:                if( err = copyin( (caddr_t)loadbufp->data, (caddr_t)curp->area + curp->offset, i))
        !           241:                        break;
        !           242: 
        !           243:                if( ( curp->offset + i) < curp->size) {
        !           244:                        lkm_state = LKMS_LOADING;
        !           245: #ifdef DEBUG
        !           246:                        printf( "LKM: LMLOADBUF (loading @ %d of %d, i = %d)\n",
        !           247:                        curp->offset, curp->size, i);
        !           248: #endif /* DEBUG*/
        !           249:                } else {
        !           250:                        lkm_state = LKMS_LOADED;
        !           251: #ifdef DEBUG
        !           252:                        printf( "LKM: LMLOADBUF (loaded)\n");
        !           253: #endif /* DEBUG*/
        !           254:                }
        !           255:                curp->offset += MODIOBUF;
        !           256:                break;
        !           257: 
        !           258:        case LMUNRESRV:         /* discard reserved pages for a module*/
        !           259:                if ((flag & FWRITE) == 0) /* only allow this if writing */
        !           260:                        return EPERM;
        !           261: 
        !           262:                lkmunreserve(); /* coerce state to LKM_IDLE*/
        !           263: #ifdef DEBUG
        !           264:                printf( "LKM: LMUNRESERV\n");
        !           265: #endif /* DEBUG*/
        !           266:                break;
        !           267: 
        !           268:        case LMREADY:           /* module loaded: call entry*/
        !           269:                if ((flag & FWRITE) == 0) /* only allow this if writing */
        !           270:                        return EPERM;
        !           271: 
        !           272:                if( lkm_state != LKMS_LOADED) {
        !           273: 
        !           274: #ifdef DEBUG
        !           275:                        printf( "lkm_state is %02x\n", lkm_state);
        !           276: #endif /* DEBUG*/
        !           277:                        err = ENXIO;
        !           278:                        break;
        !           279:                }
        !           280: 
        !           281:                curp->entry = (int (*)()) (*((int *) ( data)));
        !           282: 
        !           283:                /* call entry(load)... (assigns "private" portion)*/
        !           284:                if( err = (*(curp->entry))( curp, LKM_E_LOAD, LKM_VERSION)) {
        !           285:                        /*
        !           286:                         * Module may refuse loading or may have a
        !           287:                         * version mismatch...
        !           288:                         */
        !           289:                        lkm_state = LKMS_UNLOADING;     /* for lkmunreserve*/
        !           290:                        lkmunreserve();                 /* free memory*/
        !           291:                        curp->used = 0;                 /* free slot*/
        !           292:                        break;
        !           293:                }
        !           294: 
        !           295:                curp->used = 1;
        !           296: #ifdef DEBUG
        !           297:                printf( "LKM: LMREADY\n");
        !           298: #endif /* DEBUG*/
        !           299:                lkm_state = LKMS_IDLE;
        !           300:                break;
        !           301: 
        !           302:        case LMUNLOAD:          /* unload a module*/
        !           303:                if ((flag & FWRITE) == 0) /* only allow this if writing */
        !           304:                        return EPERM;
        !           305: 
        !           306:                unloadp = (struct lmc_unload *)data;
        !           307: 
        !           308:                if( ( i = unloadp->id) == -1) {         /* unload by name*/
        !           309:                        /*
        !           310:                         * Copy name and lookup id from all loaded
        !           311:                         * modules.
        !           312:                         */
        !           313:                        copystr( unloadp->name, istr, MAXLKMNAME-1, NULL);
        !           314:                        /*
        !           315:                         * look up id...
        !           316:                         */
        !           317:                        for( i = 0; i < MAXLKMS; i++) {
        !           318:                                if( !lkmods[ i].used)
        !           319:                                        continue;
        !           320:                                if( !strcmp( istr,
        !           321:                                        lkmods[ i].private.lkm_any->lkm_name))
        !           322:                                        break;
        !           323:                        }
        !           324:                }
        !           325: 
        !           326:                /*
        !           327:                 * Range check the value; on failure, return EINVAL
        !           328:                 */
        !           329:                if( i < 0 || i >= MAXLKMS) {
        !           330:                        err = EINVAL;
        !           331:                        break;
        !           332:                }
        !           333: 
        !           334:                curp = &lkmods[ i];
        !           335: 
        !           336:                /* call entry(unload)*/
        !           337:                if( (*(curp->entry))( curp, LKM_E_UNLOAD, LKM_VERSION)) {
        !           338:                        err = EBUSY;
        !           339:                        break;
        !           340:                }
        !           341: 
        !           342:                lkm_state = LKMS_UNLOADING;     /* non-idle for lkmunreserve*/
        !           343:                lkmunreserve();                 /* free memory*/
        !           344:                curp->used = 0;                 /* free slot*/
        !           345:                break;
        !           346: 
        !           347:        case LMSTAT:            /* stat a module by id/name*/
        !           348:                /* allow readers and writers to stat */
        !           349: 
        !           350:                statp = (struct lmc_stat *)data;
        !           351: 
        !           352:                if( ( i = statp->id) == -1) {           /* stat by name*/
        !           353:                        /*
        !           354:                         * Copy name and lookup id from all loaded
        !           355:                         * modules.
        !           356:                         */
        !           357:                        copystr( statp->name, istr, MAXLKMNAME-1, NULL);
        !           358:                        /*
        !           359:                         * look up id...
        !           360:                         */
        !           361:                        for( i = 0; i < MAXLKMS; i++) {
        !           362:                                if( !lkmods[ i].used)
        !           363:                                        continue;
        !           364:                                if( !strcmp( istr,
        !           365:                                        lkmods[ i].private.lkm_any->lkm_name))
        !           366:                                        break;
        !           367:                        }
        !           368: 
        !           369:                        if( i == MAXLKMS) {             /* Not found*/
        !           370:                                err = ENOENT;
        !           371:                                break;
        !           372:                        }
        !           373:                }
        !           374: 
        !           375:                /*
        !           376:                 * Range check the value; on failure, return EINVAL
        !           377:                 */
        !           378:                if( i < 0 || i >= MAXLKMS) {
        !           379:                        err = EINVAL;
        !           380:                        break;
        !           381:                }
        !           382: 
        !           383:                curp = &lkmods[ i];
        !           384: 
        !           385:                if( !curp->used) {                      /* Not found*/
        !           386:                        err = ENOENT;
        !           387:                        break;
        !           388:                }
        !           389: 
        !           390:                /*
        !           391:                 * Copy out stat information for this module...
        !           392:                 */
        !           393:                statp->id       = curp->id;
        !           394:                statp->offset   = curp->private.lkm_any->lkm_offset;
        !           395:                statp->type     = curp->private.lkm_any->lkm_type;
        !           396:                statp->area     = curp->area;
        !           397:                statp->size     = curp->size / PAGESIZE;
        !           398:                statp->private  = (unsigned long)curp->private.lkm_any;
        !           399:                statp->ver      = curp->private.lkm_any->lkm_ver;
        !           400:                copystr( curp->private.lkm_any->lkm_name, 
        !           401:                          statp->name,
        !           402:                          MAXLKMNAME - 2,
        !           403:                          NULL);
        !           404: 
        !           405:                break;
        !           406: 
        !           407:        default:                /* bad ioctl()...*/
        !           408:                err = ENOTTY;
        !           409:                break;
        !           410:        }
        !           411: 
        !           412:        return (err);
        !           413: }
        !           414: 
        !           415: 
        !           416: /*********************************************************************/
        !           417: 
        !           418: 
        !           419: /*
        !           420:  * l k m n o s y s
        !           421:  *
        !           422:  * Acts like "nosys" but can be identified in sysent for dynamic call
        !           423:  * number assignment for a limited number of calls.
        !           424:  *
        !           425:  * Place holder for system call slots reserved for loadable modules.
        !           426:  */
        !           427: lkmnosys()
        !           428: {
        !           429:        return( nosys());
        !           430: }
        !           431: 
        !           432: /*
        !           433:  * l k m e n o d e v
        !           434:  *
        !           435:  * Acts like "enodev", but can be identified in cdevsw and bdevsw for
        !           436:  * dynamic driver major number assignment for a limited number of
        !           437:  * drivers.
        !           438:  *
        !           439:  * Place holder for device switch slots reserved for loadable modules.
        !           440:  */
        !           441: int
        !           442: lkmenodev()
        !           443: {
        !           444:        return( enodev());
        !           445: }
        !           446: 
        !           447: /*********************************************************************/
        !           448: 
        !           449: 
        !           450: int
        !           451: lkmexists( lkmtp)
        !           452: struct lkm_table       *lkmtp;
        !           453: {
        !           454:        int     i;
        !           455: 
        !           456:        /*
        !           457:         * see if name exists...
        !           458:         */
        !           459:        for( i = 0; i < MAXLKMS; i++) {
        !           460:                /*
        !           461:                 * An unused module and the one we are testing are not
        !           462:                 * considered.
        !           463:                 */
        !           464:                if( !lkmods[ i].used || &lkmods[ i] == lkmtp)
        !           465:                        continue;
        !           466:                if( !strcmp( lkmtp->private.lkm_any->lkm_name,
        !           467:                        lkmods[ i].private.lkm_any->lkm_name))
        !           468:                        return( 1);             /* already loaded...*/
        !           469:        }
        !           470: 
        !           471:        return( 0);             /* module not loaded...*/
        !           472: }
        !           473: 
        !           474: 
        !           475: /*
        !           476:  * For the loadable system call described by the structure pointed to
        !           477:  * by lkmtp, load/unload/stat it depending on the cmd requested.
        !           478:  */
        !           479: static int
        !           480: _lkm_syscall( lkmtp, cmd)
        !           481: struct lkm_table       *lkmtp;
        !           482: int                    cmd;
        !           483: {
        !           484:        struct lkm_syscall      *args = lkmtp->private.lkm_syscall;
        !           485:        int                     i;
        !           486:        int                     err = 0;
        !           487:        extern int              nsysent;        /* init_sysent.c*/
        !           488: 
        !           489:        switch( cmd) {
        !           490:        case LKM_E_LOAD:
        !           491:                /* don't load twice!*/
        !           492:                if( lkmexists( lkmtp))
        !           493:                        return( EEXIST);
        !           494:                if( ( i = args->lkm_offset) == -1) {    /* auto*/
        !           495:                        /*
        !           496:                         * Search the table looking for a slot...
        !           497:                         */
        !           498:                        for( i = 0; i < nsysent; i++)
        !           499:                                if( sysent[ i].sy_call == lkmnosys)
        !           500:                                        break;          /* found it!*/
        !           501:                        /* out of allocable slots?*/
        !           502:                        if( i == nsysent) {
        !           503:                                err = ENFILE;
        !           504:                                break;
        !           505:                        }
        !           506:                } else {                                /* assign*/
        !           507:                        if( i < 0 || i >= nsysent) {
        !           508:                                err = EINVAL;
        !           509:                                break;
        !           510:                        }
        !           511:                }
        !           512: 
        !           513:                /* save old*/
        !           514:                bcopy( &sysent[ i], &(args->lkm_oldent), sizeof( struct sysent));
        !           515: 
        !           516:                /* replace with new*/
        !           517:                bcopy( args->lkm_sysent, &sysent[ i], sizeof( struct sysent));
        !           518: 
        !           519:                /* done!*/
        !           520:                args->lkm_offset = i;   /* slot in sysent[]*/
        !           521: 
        !           522:                break;
        !           523: 
        !           524:        case LKM_E_UNLOAD:
        !           525:                /* current slot...*/
        !           526:                i = args->lkm_offset;
        !           527: 
        !           528:                /* replace current slot contents with old contents*/
        !           529:                bcopy( &(args->lkm_oldent), &sysent[ i], sizeof( struct sysent));
        !           530: 
        !           531:                break;
        !           532: 
        !           533:        case LKM_E_STAT:        /* no special handling...*/
        !           534:                break;
        !           535:        }
        !           536: 
        !           537:        return( err);
        !           538: }
        !           539: 
        !           540: 
        !           541: /*
        !           542:  * For the loadable virtual file system described by the structure pointed
        !           543:  * to by lkmtp, load/unload/stat it depending on the cmd requested.
        !           544:  */
        !           545: static int
        !           546: _lkm_vfs( lkmtp, cmd)
        !           547: struct lkm_table       *lkmtp;
        !           548: int                    cmd;
        !           549: {
        !           550:        struct lkm_vfs          *args = lkmtp->private.lkm_vfs;
        !           551:        int                     i;
        !           552:        int                     err = 0;
        !           553: 
        !           554:        switch( cmd) {
        !           555:        case LKM_E_LOAD:
        !           556:                /* don't load twice!*/
        !           557:                if( lkmexists( lkmtp))
        !           558:                        return( EEXIST);
        !           559:                /*
        !           560:                 * Currently, the VFS and mount code in 386BSD is malformed;
        !           561:                 * this means that the per volume file system identifier is
        !           562:                 * the index into the table rather than the name; this means
        !           563:                 * that only the file systems already known to 386BSD are
        !           564:                 * allowable, since all others don't have fixed offsets.
        !           565:                 * Interestingly, Dell UNIX has this same bug with their VFS
        !           566:                 * implementation, but generic AT&T SVR4 does not.
        !           567:                 *
        !           568:                 * I will correct the VFS code when I get a chance.
        !           569:                 */
        !           570:                i = args->lkm_offset;
        !           571:                if( i < 0 || i > MOUNT_MAXTYPE) {
        !           572:                        err = EINVAL;
        !           573:                        break;
        !           574:                }
        !           575: 
        !           576:                if( vfssw[ i] != (struct vfsops *)0) {
        !           577:                        err = EEXIST;
        !           578:                        break;
        !           579:                }
        !           580: 
        !           581:                /*
        !           582:                 * Set up file system
        !           583:                 */
        !           584:                vfssw[ i] = args->lkm_vfsops;
        !           585: 
        !           586:                /*
        !           587:                 * Call init function for this VFS...
        !           588:                 */
        !           589:                ( *(vfssw[ i]->vfs_init))( args->lkm_flags);
        !           590: 
        !           591:                /* done!*/
        !           592:                args->lkm_offset = i;   /* slot in sysent[]*/
        !           593: 
        !           594:                break;
        !           595: 
        !           596:        case LKM_E_UNLOAD:
        !           597:                /* current slot...*/
        !           598:                i = args->lkm_offset;
        !           599: 
        !           600:                /* replace current slot contents with old contents*/
        !           601:                vfssw[ i] = (struct vfsops *)0;
        !           602: 
        !           603:                break;
        !           604: 
        !           605:        case LKM_E_STAT:        /* no special handling...*/
        !           606:                break;
        !           607:        }
        !           608: 
        !           609:        return( err);
        !           610: }
        !           611: 
        !           612: 
        !           613: /*
        !           614:  * For the loadable device driver described by the structure pointed to
        !           615:  * by lkmtp, load/unload/stat it depending on the cmd requested.
        !           616:  */
        !           617: static int
        !           618: _lkm_dev( lkmtp, cmd)
        !           619: struct lkm_table       *lkmtp;
        !           620: int                    cmd;
        !           621: {
        !           622:        struct lkm_dev          *args = lkmtp->private.lkm_dev;
        !           623:        int                     i;
        !           624:        int                     err = 0;
        !           625:        extern int              nblkdev;        /* i386/i386/conf.c*/
        !           626:        extern int              nchrdev;        /* i386/i386/conf.c*/
        !           627: 
        !           628:        switch( cmd) {
        !           629:        case LKM_E_LOAD:
        !           630:                /* don't load twice!*/
        !           631:                if( lkmexists( lkmtp))
        !           632:                        return( EEXIST);
        !           633:                switch( args->lkm_devtype) {
        !           634:                case LM_DT_BLOCK:
        !           635:                        if( ( i = args->lkm_offset) == -1) {    /* auto*/
        !           636:                                /*
        !           637:                                 * Search the table looking for a slot...
        !           638:                                 */
        !           639:                                for( i = 0; i < nblkdev; i++)
        !           640:                                        if( bdevsw[ i].d_open == lkmenodev)
        !           641:                                                break;          /* found it!*/
        !           642:                                /* out of allocable slots?*/
        !           643:                                if( i == nblkdev) {
        !           644:                                        err = ENFILE;
        !           645:                                        break;
        !           646:                                }
        !           647:                        } else {                                /* assign*/
        !           648:                                if( i < 0 || i >= nblkdev) {
        !           649:                                        err = EINVAL;
        !           650:                                        break;
        !           651:                                }
        !           652:                        }
        !           653: 
        !           654:                        /* save old*/
        !           655:                        bcopy( &bdevsw[ i], &(args->lkm_olddev.bdev), sizeof( struct bdevsw));
        !           656: 
        !           657:                        /* replace with new*/
        !           658:                        bcopy( args->lkm_dev.bdev, &bdevsw[ i], sizeof( struct bdevsw));
        !           659: 
        !           660:                        /* done!*/
        !           661:                        args->lkm_offset = i;   /* slot in bdevsw[]*/
        !           662:                        break;
        !           663: 
        !           664:                case LM_DT_CHAR:
        !           665:                        if( ( i = args->lkm_offset) == -1) {    /* auto*/
        !           666:                                /*
        !           667:                                 * Search the table looking for a slot...
        !           668:                                 */
        !           669:                                for( i = 0; i < nchrdev; i++)
        !           670:                                        if( cdevsw[ i].d_open == lkmenodev)
        !           671:                                                break;          /* found it!*/
        !           672:                                /* out of allocable slots?*/
        !           673:                                if( i == nchrdev) {
        !           674:                                        err = ENFILE;
        !           675:                                        break;
        !           676:                                }
        !           677:                        } else {                                /* assign*/
        !           678:                                if( i < 0 || i >= nchrdev) {
        !           679:                                        err = EINVAL;
        !           680:                                        break;
        !           681:                                }
        !           682:                        }
        !           683: 
        !           684:                        /* save old*/
        !           685:                        bcopy( &cdevsw[ i], &(args->lkm_olddev.cdev), sizeof( struct cdevsw));
        !           686: 
        !           687:                        /* replace with new*/
        !           688:                        bcopy( args->lkm_dev.cdev, &cdevsw[ i], sizeof( struct cdevsw));
        !           689: 
        !           690:                        /* done!*/
        !           691:                        args->lkm_offset = i;   /* slot in cdevsw[]*/
        !           692: 
        !           693:                        break;
        !           694: 
        !           695:                default:
        !           696:                        err = ENODEV;
        !           697:                        break;
        !           698:                }
        !           699:                break;
        !           700: 
        !           701:        case LKM_E_UNLOAD:
        !           702:                /* current slot...*/
        !           703:                i = args->lkm_offset;
        !           704: 
        !           705:                switch( args->lkm_devtype) {
        !           706:                case LM_DT_BLOCK:
        !           707:                        /* replace current slot contents with old contents*/
        !           708:                        bcopy( &(args->lkm_olddev.bdev), &bdevsw[ i], sizeof( struct bdevsw));
        !           709:                        break;
        !           710: 
        !           711:                case LM_DT_CHAR:
        !           712:                        /* replace current slot contents with old contents*/
        !           713:                        bcopy( &(args->lkm_olddev.cdev), &cdevsw[ i], sizeof( struct cdevsw));
        !           714:                        break;
        !           715: 
        !           716:                default:
        !           717:                        err = ENODEV;
        !           718:                        break;
        !           719:                }
        !           720:                break;
        !           721: 
        !           722:        case LKM_E_STAT:        /* no special handling...*/
        !           723:                break;
        !           724:        }
        !           725: 
        !           726:        return( err);
        !           727: }
        !           728: 
        !           729: 
        !           730: #ifdef STREAMS
        !           731: /*
        !           732:  * For the loadable streams module described by the structure pointed to
        !           733:  * by lkmtp, load/unload/stat it depending on the cmd requested.
        !           734:  */
        !           735: static int
        !           736: _lkm_strmod( lkmtp, cmd)
        !           737: struct lkm_table       *lkmtp;
        !           738: int                    cmd;
        !           739: {
        !           740:        struct lkm_strmod       *args = lkmtp->private.lkm_strmod;
        !           741:        int                     i;
        !           742:        int                     err = 0;
        !           743: 
        !           744:        switch( cmd) {
        !           745:        case LKM_E_LOAD:
        !           746:                /* don't load twice!*/
        !           747:                if( lkmexists( lkmtp))
        !           748:                        return( EEXIST);
        !           749:                break;
        !           750: 
        !           751:        case LKM_E_UNLOAD:
        !           752:                break;
        !           753: 
        !           754:        case LKM_E_STAT:        /* no special handling...*/
        !           755:                break;
        !           756:        }
        !           757: 
        !           758:        return( err);
        !           759: }
        !           760: #endif /* STREAMS*/
        !           761: 
        !           762: #ifdef LKM_EXEC /* XXX NOTDEF YET!!! - cgd */
        !           763: /*
        !           764:  * For the loadable execution class described by the structure pointed to
        !           765:  * by lkmtp, load/unload/stat it depending on the cmd requested.
        !           766:  */
        !           767: static int
        !           768: _lkm_exec( lkmtp, cmd)
        !           769: struct lkm_table       *lkmtp;
        !           770: int                    cmd;
        !           771: {
        !           772:        struct lkm_exec         *args = lkmtp->private.lkm_exec;
        !           773:        int                     i;
        !           774:        int                     err = 0;
        !           775: 
        !           776:        switch( cmd) {
        !           777:        case LKM_E_LOAD:
        !           778:                /* don't load twice!*/
        !           779:                if( lkmexists( lkmtp))
        !           780:                        return( EEXIST);
        !           781:                if( ( i = args->lkm_offset) == -1) {    /* auto*/
        !           782:                        /*
        !           783:                         * Search the table looking for a slot...
        !           784:                         */
        !           785:                        for( i = 0; i < nexecs; i++)
        !           786:                                if( execsw[ i].m_size == 0)
        !           787:                                        break;          /* found it!*/
        !           788:                        /* out of allocable slots?*/
        !           789:                        if( i == nexecs) {
        !           790:                                err = ENFILE;
        !           791:                                break;
        !           792:                        }
        !           793:                } else {                                /* assign*/
        !           794:                        if( i < 0 || i >= nexecs) {
        !           795:                                err = EINVAL;
        !           796:                                break;
        !           797:                        }
        !           798:                }
        !           799: 
        !           800:                /* save old*/
        !           801:                bcopy( &execsw[ i], &(args->lkm_oldexec), sizeof( struct execsw));
        !           802: 
        !           803:                /* replace with new*/
        !           804:                bcopy( args->lkm_exec, &execsw[ i], sizeof( struct execsw));
        !           805: 
        !           806:                /* done!*/
        !           807:                args->lkm_offset = i;   /* slot in execsw[]*/
        !           808: 
        !           809:                break;
        !           810: 
        !           811:        case LKM_E_UNLOAD:
        !           812:                /* current slot...*/
        !           813:                i = args->lkm_offset;
        !           814: 
        !           815:                /* replace current slot contents with old contents*/
        !           816:                bcopy( &execsw[ i], &(args->lkm_oldexec), sizeof( struct execsw));
        !           817: 
        !           818:                break;
        !           819: 
        !           820:        case LKM_E_STAT:        /* no special handling...*/
        !           821:                break;
        !           822:        }
        !           823: 
        !           824:        return( err);
        !           825: }
        !           826: #endif /* LKM_EXEC */
        !           827: 
        !           828: /*
        !           829:  * This code handles the per-module type "wiring-in" of loadable modules
        !           830:  * into existing kernel tables.  For "LM_MISC" modules, wiring and unwiring
        !           831:  * is assumed to be done in their entry routines internal to the module
        !           832:  * itself.
        !           833:  */
        !           834: lkmdispatch( lkmtp, cmd)
        !           835: struct lkm_table       *lkmtp; 
        !           836: int                    cmd;
        !           837: {
        !           838:        int     err = 0;                /* default = success*/
        !           839: 
        !           840:        switch( lkmtp->private.lkm_any->lkm_type) {
        !           841:        case LM_SYSCALL:
        !           842:                err = _lkm_syscall( lkmtp, cmd);
        !           843:                break;
        !           844: 
        !           845:        case LM_VFS:
        !           846:                err = _lkm_vfs( lkmtp, cmd);
        !           847:                break;
        !           848: 
        !           849:        case LM_DEV:
        !           850:            {
        !           851:                struct lkm_dev  *args = lkmtp->private.lkm_dev;
        !           852:            }
        !           853:            break;
        !           854: 
        !           855: #ifdef STREAMS
        !           856:        case LM_STRMOD:
        !           857:            {
        !           858:                struct lkm_strmod       *args = lkmtp->private.lkm_strmod;
        !           859:            }
        !           860:            break;
        !           861: 
        !           862: #endif /* STREAMS*/
        !           863: 
        !           864: #ifdef LKM_EXEC
        !           865:        case LM_EXEC:
        !           866:                err = _lkm_exec( lkmtp, cmd);
        !           867:                break;
        !           868: #endif /* LKM_EXEC */
        !           869: 
        !           870:        case LM_MISC:   /* ignore content -- no "misc-specific" procedure*/
        !           871:            break;
        !           872: 
        !           873:        default:
        !           874:            err = ENXIO;        /* unknown type*/
        !           875:            break;
        !           876:        }
        !           877: 
        !           878:        return( err);
        !           879: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.