Annotation of coherent/b/STREAMS/conf/bin/src/assign.c, revision 1.1.1.1

1.1       root        1: #define        _DDI_DKI        1
                      2: #define        _SYSV4          1
                      3: 
                      4: /*
                      5:  * This file assigns device major and minor numbers based on configuration
                      6:  * data read in by "devadm.c".
                      7:  */
                      8: /*
                      9:  *-IMPORTS:
                     10:  *     <sys/compat.h>
                     11:  *             CONST
                     12:  *             PROTO
                     13:  *             ARGS ()
                     14:  *             LOCAL
                     15:  *     <kernel/v_types.h>
                     16:  *             NODEV
                     17:  *             major_t
                     18:  *             minor_t
                     19:  *     <stddef.h>
                     20:  *             size_t
                     21:  *             offsetof ()
                     22:  *     <stdlib.h>
                     23:  *             NULL
                     24:  *             free ()
                     25:  *             malloc ()
                     26:  *     "ehand.h"
                     27:  *             throw_error ()
                     28:  *     "mdev.h"
                     29:  *             mdev_t
                     30:  *             mdev_sort ()
                     31:  */
                     32: 
                     33: #include <sys/compat.h>
                     34: #include <kernel/v_types.h>
                     35: #include <stddef.h>
                     36: #include <stdlib.h>
                     37: 
                     38: #include "ehand.h"
                     39: #include "mdev.h"
                     40: 
                     41: #include "assign.h"
                     42: 
                     43: /*
                     44:  * Selection predicate for choosing enabled character devices.
                     45:  */
                     46: 
                     47: #if    USE_PROTO
                     48: LOCAL int chr_sel (mdev_t * mdevp)
                     49: #else
                     50: LOCAL int
                     51: chr_sel (mdevp)
                     52: mdev_t       * mdevp;
                     53: #endif
                     54: {
                     55:        return mdevp->md_configure == MD_ENABLED &&
                     56:               mdev_flag (mdevp, MDEV_CHAR);
                     57: }
                     58: 
                     59: 
                     60: /*
                     61:  * Predicate for comparing two mdevice entries on the basis of minimum
                     62:  * external character-device number.
                     63:  */
                     64: 
                     65: #if    USE_PROTO
                     66: LOCAL int chr_pred (mdev_t * left, mdev_t * right)
                     67: #else
                     68: LOCAL int
                     69: chr_pred (left, right)
                     70: mdev_t       * left;
                     71: mdev_t       * right;
                     72: #endif
                     73: {
                     74:        return left->md_chr_maj [0] < right->md_chr_maj [0];
                     75: }
                     76: 
                     77: 
                     78: /*
                     79:  * Selection predicate for choosing enabled block devices.
                     80:  */
                     81: 
                     82: #if    USE_PROTO
                     83: LOCAL int blk_sel (mdev_t * mdevp)
                     84: #else
                     85: LOCAL int
                     86: blk_sel (mdevp)
                     87: mdev_t       * mdevp;
                     88: #endif
                     89: {
                     90:        return mdevp->md_configure == MD_ENABLED &&
                     91:               mdev_flag (mdevp, MDEV_BLOCK);
                     92: }
                     93: 
                     94: 
                     95: /*
                     96:  * Predicate for comparing two mdevice entries on the basis of minimum
                     97:  * external block-device number.
                     98:  */
                     99: 
                    100: #if    USE_PROTO
                    101: LOCAL int blk_pred (mdev_t * left, mdev_t * right)
                    102: #else
                    103: LOCAL int
                    104: blk_pred (left, right)
                    105: mdev_t       * left;
                    106: mdev_t       * right;
                    107: #endif
                    108: {
                    109:        return left->md_blk_maj [0] < right->md_blk_maj [0];
                    110: }
                    111: 
                    112: 
                    113: /*
                    114:  * Predicate for selecting modules (streams drivers that are not devices).
                    115:  */
                    116: 
                    117: #if    USE_PROTO
                    118: LOCAL int mod_sel (mdev_t * mdevp)
                    119: #else
                    120: LOCAL int
                    121: mod_sel (mdevp)
                    122: mdev_t       * mdevp;
                    123: #endif
                    124: {
                    125:        return mdevp->md_configure == MD_ENABLED &&
                    126:               mdev_flag (mdevp, MDEV_STREAM) &&
                    127:               ! mdev_flag (mdevp, MDEV_CHAR);
                    128: }
                    129: 
                    130: 
                    131: /*
                    132:  * Predicate for selecting Coherent drivers.
                    133:  */
                    134: 
                    135: #if    USE_PROTO
                    136: LOCAL int coh_sel (mdev_t * mdevp)
                    137: #else
                    138: LOCAL int
                    139: coh_sel (mdevp)
                    140: mdev_t       * mdevp;
                    141: #endif
                    142: {
                    143:        return mdevp->md_configure == MD_ENABLED &&
                    144:               mdev_flag (mdevp, MDEV_COHERENT);
                    145: }
                    146: 
                    147: 
                    148: /*
                    149:  * Predicate for comparing two Coherent devices on the basis of major number.
                    150:  */
                    151: 
                    152: #if    USE_PROTO
                    153: LOCAL int coh_pred (mdev_t * left, mdev_t * right)
                    154: #else
                    155: LOCAL int
                    156: coh_pred (left, right)
                    157: mdev_t       * left;
                    158: mdev_t       * right;
                    159: #endif
                    160: {
                    161:        return left->md_blk_maj [0] < right->md_blk_maj [0];
                    162: }
                    163: 
                    164: 
                    165: /*
                    166:  * This is where we build the external->internal major number mapping table.
                    167:  *
                    168:  * The external->internal device number system becomes immediately useful
                    169:  * under STREAMS, where a) STREAMS cannot use device major numbers lower than
                    170:  * MAJOR_RESERVED under Coherent, and b) Coherent uses old-style 16-bit
                    171:  * dev_t's, so that the ability to transform a range of external majors into
                    172:  * a contiguous sequence of internal minor numbers will be of immediate value
                    173:  * in supporting connection-oriented services (although this is also pending
                    174:  * on the addition of support for cloning to the kernel).
                    175:  *
                    176:  * Mapping between internal and external numbers is not simple; what makes it
                    177:  * worse is that because there is a single mapping that has to be the same
                    178:  * for both block and character tables, the construction of the bdevsw [] and
                    179:  * cdevsw [] internal tables is constrained. This is only a problem if
                    180:  * multiple external major numbers are allowed, and each device is only
                    181:  * permitted to have a single internal major number. The interpretation of the
                    182:  * 'M' flag in this circumstance is unclear.
                    183:  *
                    184:  * The assign_imajors () code should be able to deal with the most complex
                    185:  * case, which is where multiple external majors may actually be mapped to
                    186:  * multiple internal numbers, thus
                    187:  *
                    188:  *     Block external :            |-----scsi-------|
                    189:  *     Character external:   |--tcp--| |-udp-|  |ttys|
                    190:  *
                    191:  * Might map 'tcp' to internal 0, 'udp' to internal 1, 'ttys' to internal 2,
                    192:  * while 'scsi' would have 0, 1, and 2 as internal major numbers.
                    193:  *
                    194:  * This is all hypothetical at the moment, since multiple majors are new to
                    195:  * Coherent anyway. For simplicity, we may constrain the above to be an error
                    196:  * by requiring unique internal number for each device. However, the machinery
                    197:  * in assign_imajors () will have to be flexible enough to deal with the
                    198:  * above.
                    199:  *
                    200:  * NOTE: The complex model is only applicable if a device does not care what
                    201:  * minor numbers are given to it, since there is a single shared table used
                    202:  * to map a range of external major numbers into a range of internal minor
                    203:  * numbers. Since this table is shared, it constrains even more heavily the
                    204:  * circumstances in which numbers can overlap. Without a flag to detect when
                    205:  * a driver doesn't care about minor numbers, we simply forget about the
                    206:  * complex model.
                    207:  */
                    208: 
                    209: /*
                    210:  * Definitions used to control parts of the way assign_imajors () deals with
                    211:  * the external->internal mapping (as discussed above). The main things we
                    212:  * isolate here are the calculations of the upper bounds for table allocations
                    213:  * since the constraint of a common mapping means that the cdevsw [] and
                    214:  * bdevsw [] tables may be larger than a separate mapping would permit.
                    215:  *
                    216:  * In particular, if ncdevs is the number of character devices and nbdevs is
                    217:  * the number of block devices, the upper bound on table size is:
                    218:  *     Simple model:   block = char = max (ncdevs, nbdevs)
                    219:  *     Complex model:  char = ncdevs + max (nbdevs - 1, 0)
                    220:  *                     block = nbdevs + max (ncdevs - 1, 0)
                    221:  */
                    222: 
                    223: #define        MAX(a,b)                ((a) > (b) ? (a) : (b))
                    224: #define        MIN(a,b)                ((a) < (b) ? (a) : (b))
                    225: 
                    226: #define        MAX_CHR_IMAJORS(c,b)    MAX (c, b)
                    227: #define        MAX_BLK_IMAJORS(c,b)    MAX (c, b)
                    228: 
                    229: 
                    230: /*
                    231:  * Assign internal major numbers to devices. For now, this function does not
                    232:  * attempt to deal with assigning major number ranges.
                    233:  */
                    234: 
                    235: #if    USE_PROTO
                    236: extinfo_t * (assign_imajors) (void)
                    237: #else
                    238: extinfo_t *
                    239: assign_imajors ARGS (())
                    240: #endif
                    241: {
                    242:        extinfo_t     * extinfop;
                    243:        mdev_t        * blk_list;
                    244:        mdev_t        * blk_end;
                    245:        mdev_t        * chr_list;
                    246:        mdev_t        * chr_end;
                    247:        mdev_t        * mod_list;
                    248:        mdev_t        * coh_list;
                    249:        int             n_blk_list;
                    250:        int             n_chr_list;
                    251:        int             n_mod_list;
                    252:        int             n_coh_list;
                    253: 
                    254:        int             nemajors;
                    255:        int             i;
                    256: 
                    257: 
                    258:        /*
                    259:         * The algorithm for assigning internal numbers for the block and
                    260:         * character-device tables will be able to run in a single pass if we
                    261:         * are able to provide lists of character and block devices sorted by
                    262:         * beginning external major number. This sort process also provides us
                    263:         * a variety of other useful information directly, such as the maximum
                    264:         * external number used.
                    265:         */
                    266: 
                    267:        n_chr_list = mdev_sort (& chr_list, & chr_end, chr_sel, chr_pred,
                    268:                                offsetof (mdev_t, md_chrlink));
                    269:        n_blk_list = mdev_sort (& blk_list, & blk_end, blk_sel, blk_pred,
                    270:                                offsetof (mdev_t, md_blklink));
                    271:        n_mod_list = mdev_sort (& mod_list, NULL, mod_sel, NULL,
                    272:                                offsetof (mdev_t, md_modlink));
                    273:        n_coh_list = mdev_sort (& coh_list, NULL, coh_sel, coh_pred,
                    274:                                offsetof (mdev_t, md_cohlink));
                    275: 
                    276:        nemajors = 0;
                    277: 
                    278:        if (chr_end != NULL)
                    279:                nemajors = MAX (nemajors, chr_end->md_chr_maj [1]);
                    280: 
                    281:        if (blk_end != NULL)
                    282:                nemajors = MAX (nemajors, blk_end->md_blk_maj [1]);
                    283: 
                    284:        nemajors ++;
                    285: 
                    286: 
                    287:        /*
                    288:         * Now we know how many of everything there is, allocate space for
                    289:         * tables.
                    290:         */
                    291: 
                    292:        i = sizeof (* extinfop) +
                    293:            sizeof (mdev_t *) * (MAX_CHR_IMAJORS (n_chr_list, n_blk_list) +
                    294:                                 MAX_BLK_IMAJORS (n_chr_list, n_blk_list) +
                    295:                                 n_mod_list + n_coh_list) +
                    296:            2 * sizeof (minor_t) * nemajors;
                    297: 
                    298:        if ((extinfop = (extinfo_t *) malloc (i)) == NULL)
                    299:                throw_error ("insufficient memory in assign_imajors ()");
                    300: 
                    301:        extinfop->ei_etoimajor = (minor_t *) (extinfop + 1);
                    302:        extinfop->ei_minoroffset = extinfop->ei_etoimajor + nemajors;
                    303:        extinfop->ei_modules = (mdev_t **) (extinfop->ei_minoroffset +
                    304:                                            nemajors);
                    305:        extinfop->ei_cohdrivers = extinfop->ei_modules + n_mod_list;
                    306:        extinfop->ei_cdevsw = extinfop->ei_cohdrivers + n_coh_list;
                    307:        extinfop->ei_bdevsw = extinfop->ei_cdevsw +
                    308:                                MAX_CHR_IMAJORS (n_chr_list, n_blk_list);
                    309: 
                    310:        /*
                    311:         * Since we allocate space for the maximum number of table entries,
                    312:         * the loops below assign internal numbers which may not be
                    313:         * contiguous, or may be below the upper limit allocated.
                    314:         */
                    315: 
                    316:        extinfop->ei_nemajors = nemajors;
                    317:        extinfop->ei_ncdevs = 0;
                    318:        extinfop->ei_nbdevs = 0;
                    319:        extinfop->ei_nmodules = n_mod_list;
                    320:        extinfop->ei_ncohdrivers = n_coh_list;
                    321: 
                    322:        for (i = 0 ; i < nemajors ; i ++) {
                    323: 
                    324:                extinfop->ei_etoimajor [i] = NODEV;
                    325:                extinfop->ei_minoroffset [i] = 0;
                    326:        }
                    327: 
                    328: 
                    329:        for (i = 0 ; i < MAX_CHR_IMAJORS (n_chr_list, n_blk_list) ; i ++)
                    330:                extinfop->ei_cdevsw [i] = NULL;
                    331: 
                    332:        for (i = 0 ; i < MAX_BLK_IMAJORS (n_chr_list, n_blk_list) ; i ++)
                    333:                extinfop->ei_bdevsw [i] = NULL;
                    334: 
                    335: 
                    336:        while (chr_list != NULL || blk_list != NULL) {
                    337:                mdev_t        * chrp;
                    338:                mdev_t        * blkp;
                    339:                int             extlo;
                    340:                int             exthi;
                    341:                int             internal;
                    342:                int             minorinc;
                    343:                int             minorofs;
                    344: 
                    345:                /*
                    346:                 * Choose a range of external numbers that we are going to
                    347:                 * assign to a single internal number. If our choice is not
                    348:                 * constrained by an overlap between character and block
                    349:                 * external numbers, then we deal with that.
                    350:                 */
                    351: 
                    352:                blkp = blk_list;
                    353: 
                    354:                if ((chrp = chr_list) != NULL) {
                    355: 
                    356:                        extlo = chrp->md_chr_maj [0];
                    357:                        exthi = chrp->md_chr_maj [1];
                    358:                        minorinc = chrp->md_minor_max;
                    359: 
                    360:                        if (blkp != NULL) {
                    361: 
                    362:                                if (blkp->md_blk_maj [1] < extlo) {
                    363: 
                    364:                                        chrp = NULL;
                    365:                                        goto doblock;
                    366:                                }
                    367: 
                    368:                                if (blkp->md_blk_maj [0] > exthi) {
                    369:                                        blkp = NULL;
                    370:                                        goto dochar;
                    371:                                }
                    372: 
                    373:                                /*
                    374:                                 * Because of minor-number mapping, overlap is
                    375:                                 * only valid in special circumstances.
                    376:                                 */
                    377: 
                    378:                                if (blkp->md_blk_maj [0] != extlo ||
                    379:                                    (blkp->md_minor_max != minorinc &&
                    380:                                     blkp->md_blk_maj [1] >
                    381:                                                blkp->md_blk_maj [0] &&
                    382:                                     exthi > extlo)) {
                    383: 
                    384:                                        free (extinfop);
                    385:                                        throw_error ("minor number mapping conflict");
                    386:                                }
                    387: 
                    388: 
                    389:                                /*
                    390:                                 * Choose a suitable internal major number.
                    391:                                 */
                    392: 
                    393:                                if (exthi < blkp->md_blk_maj [1]) {
                    394: 
                    395:                                        exthi = blkp->md_blk_maj [1];
                    396:                                        minorinc = blkp->md_minor_max;
                    397:                                }
                    398: 
                    399:                                internal = MAX (extinfop->ei_ncdevs,
                    400:                                                extinfop->ei_nbdevs);
                    401: 
                    402:                                goto done;
                    403:                        }
                    404: dochar:
                    405:                        /*
                    406:                         * Simple case, select an internal number.
                    407:                         */
                    408: 
                    409:                        for (internal = 0 ;
                    410:                             extinfop->ei_cdevsw [internal] != NULL ;
                    411:                             internal ++)
                    412:                                ;
                    413: 
                    414:                        if (internal > extinfop->ei_ncdevs) {
                    415: 
                    416:                                free (extinfop);
                    417:                                throw_error ("internal check failed, assign_imajors ()");
                    418:                        }
                    419:                } else {
                    420:                        /*
                    421:                         * Simple case for block device, select an internal
                    422:                         * number.
                    423:                         */
                    424: 
                    425: doblock:
                    426:                        extlo = blkp->md_blk_maj [0];
                    427:                        exthi = blkp->md_blk_maj [1];
                    428:                        minorinc = blkp->md_minor_max;
                    429: 
                    430:                        for (internal = 0 ;
                    431:                             extinfop->ei_bdevsw [internal] != NULL ;
                    432:                             internal ++)
                    433:                                ;
                    434: 
                    435:                        if (internal > extinfop->ei_nbdevs) {
                    436: 
                    437:                                free (extinfop);
                    438:                                throw_error ("internal check failed, assign_imajors ()");
                    439:                        }
                    440:                }
                    441: done:
                    442:                /*
                    443:                 * Now we have decided when, where, and how much, fill in the
                    444:                 * table.
                    445:                 */
                    446: 
                    447:                minorofs = 0;
                    448: 
                    449:                while (extlo <= exthi) {
                    450: 
                    451:                        if (extinfop->ei_etoimajor [extlo] != NODEV) {
                    452: 
                    453:                                free (extinfop);
                    454:                                throw_error ("major-number mapping conflict");
                    455:                        }
                    456: 
                    457:                        extinfop->ei_etoimajor [extlo] = internal;
                    458:                        extinfop->ei_minoroffset [extlo] = minorofs;
                    459: 
                    460:                        minorofs += minorinc;
                    461:                        extlo ++;
                    462:                }
                    463: 
                    464:                if ((extinfop->ei_cdevsw [internal] = chrp) != NULL) {
                    465: 
                    466:                        if (internal >= extinfop->ei_ncdevs)
                    467:                                extinfop->ei_ncdevs = internal + 1;
                    468: 
                    469:                        chr_list = chrp->md_chrlink;
                    470:                }
                    471: 
                    472: 
                    473:                if ((extinfop->ei_bdevsw [internal] = blkp) != NULL) {
                    474: 
                    475:                        if (internal >= extinfop->ei_nbdevs)
                    476:                                extinfop->ei_nbdevs = internal + 1;
                    477: 
                    478:                        blk_list = blkp->md_blklink;
                    479:                }
                    480:        }
                    481: 
                    482: 
                    483:        /*
                    484:         * Now we can build a table of all the STREAMS modules.
                    485:         */
                    486: 
                    487:        i = 0;
                    488: 
                    489:        while (mod_list != NULL) {
                    490: 
                    491:                extinfop->ei_modules [i ++] = mod_list;
                    492:                mod_list = mod_list->md_modlink;
                    493:        }
                    494: 
                    495: 
                    496:        /*
                    497:         * Now we can build a table of all the Coherent drivers.
                    498:         */
                    499: 
                    500:        i = 0;
                    501: 
                    502:        while (coh_list != NULL) {
                    503: 
                    504:                extinfop->ei_cohdrivers [i ++] = coh_list;
                    505:                coh_list = coh_list->md_cohlink;
                    506:        }
                    507: 
                    508:        return extinfop;
                    509: }
                    510: 

unix.superglobalmegacorp.com

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