Annotation of coherent/b/STREAMS/coh.386/fs3.c, revision 1.1.1.1

1.1       root        1: /* $Header: /src386/STREAMS/coh.386/RCS/fs3.c,v 2.3 93/08/09 13:35:38 bin Exp Locker: bin $ */
                      2: /* (lgl-
                      3:  *     The information contained herein is a trade secret of Mark Williams
                      4:  *     Company, and  is confidential information.  It is provided  under a
                      5:  *     license agreement,  and may be  copied or disclosed  only under the
                      6:  *     terms of  that agreement.  Any  reproduction or disclosure  of this
                      7:  *     material without the express written authorization of Mark Williams
                      8:  *     Company or persuant to the license agreement is unlawful.
                      9:  *
                     10:  *     COHERENT Version 2.3.37
                     11:  *     Copyright (c) 1982, 1983, 1984.
                     12:  *     An unpublished work by Mark Williams Company, Chicago.
                     13:  *     All rights reserved.
                     14:  -lgl) */
                     15: /*
                     16:  * Coherent.
                     17:  * Filesystem (I/O).
                     18:  *
                     19:  * $Log:       fs3.c,v $
                     20:  * Revision 2.3  93/08/09  13:35:38  bin
                     21:  * Kernel 82 changes
                     22:  * 
                     23:  * Revision 2.2  93/07/26  14:28:33  nigel
                     24:  * Nigel's R80
                     25:  * 
                     26:  * Revision 1.5  93/04/14  10:06:33  root
                     27:  * r75
                     28:  * 
                     29:  * Revision 1.2  92/01/06  11:59:34  hal
                     30:  * Compile with cc.mwc.
                     31:  * 
                     32:  * Revision 1.1        88/03/24  16:13:54      src
                     33:  * Initial revision
                     34:  * 
                     35:  * 87/11/25    Allan Cornish           /usr/src/sys/coh/fs3.c
                     36:  * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
                     37:  *
                     38:  * 86/02/01    Allan Cornish
                     39:  * Added code to fwrite() to avoid needless writing of pipe blocks.
                     40:  * Throughput on 6 Mhz AT rose from 30 Kbytes/sec to 79 Kbytes/sec.
                     41:  */
                     42: 
                     43: #include <common/_tricks.h>
                     44: #include <sys/debug.h>
                     45: #include <sys/coherent.h>
                     46: #include <sys/buf.h>
                     47: #include <canon.h>
                     48: #include <sys/con.h>
                     49: #include <sys/errno.h>
                     50: #include <sys/filsys.h>
                     51: #include <sys/mount.h>
                     52: #include <sys/io.h>
                     53: #include <sys/ino.h>
                     54: #include <sys/inode.h>
                     55: #include <sys/stat.h>
                     56: #include <sys/file.h>
                     57: 
                     58: /*
                     59:  * Given an inode, open it.
                     60:  */
                     61: iopen(ip, mode)
                     62: register INODE *ip;
                     63: {
                     64:        register int type;
                     65: 
                     66:        type = ip->i_mode & IFMT;
                     67:        switch (type) {
                     68:        case IFCHR:
                     69:        case IFBLK:
                     70:                iunlock(ip);
                     71:                dopen(ip->i_a.i_rdev, mode, type==IFCHR ? DFCHR : DFBLK);
                     72:                ilock(ip);
                     73:                break;
                     74:        case IFDIR:
                     75:                if (mode & IPW) {
                     76: 
                     77:                        /* Return (EISDIR) if not superuser. */
                     78:                        if (super() == 0) {
                     79:                                /* Override EPERM set when super() failed. */
                     80:                                u.u_error = EISDIR;
                     81:                                return;
                     82:                        }
                     83: 
                     84:                        /*
                     85:                         * Opening a directory O_WRONLY is insane, even
                     86:                         * if you are superuser!
                     87:                         */
                     88:                        if (mode == IPW) {
                     89:                                u.u_error = EISDIR;
                     90:                                return;
                     91:                        }
                     92:                }
                     93:                break;
                     94:        case IFPIPE:
                     95:                popen(ip, mode);
                     96:                break;
                     97:        }
                     98: }
                     99: 
                    100: /*
                    101:  * Given an inode, close it.
                    102:  *
                    103:  * NIGEL: Modified for new dclose ().
                    104:  */
                    105: iclose(ip, mode)
                    106: register INODE *ip;
                    107: {
                    108:        register int type;
                    109: 
                    110:        ilock(ip);
                    111:        switch (type = ip->i_mode&IFMT) {
                    112:        case IFBLK:
                    113:                bflush(ip->i_a.i_rdev);
                    114:                /* FALL THROUGH */
                    115:        case IFCHR:
                    116:                iunlock(ip);
                    117:                dclose(ip->i_a.i_rdev, mode,  type==IFCHR ? DFCHR : DFBLK);
                    118:                ilock(ip);
                    119:                break;
                    120: 
                    121:        case IFPIPE:
                    122:                pclose(ip, mode);
                    123:                break;
                    124:        }
                    125:        idetach(ip);
                    126: }
                    127: 
                    128: /*
                    129:  * Read from a file described by an inode and an io strucuture.
                    130:  */
                    131: iread(ip, iop)
                    132: register INODE *ip;
                    133: register IO *iop;
                    134: {
                    135:        if (iop->io_ioc == 0)
                    136:                return;
                    137: 
                    138:        switch (ip->i_mode & IFMT) {
                    139:        case IFCHR:
                    140:                dread (ip->i_a.i_rdev, iop);
                    141:                break;
                    142: 
                    143:        case IFBLK:
                    144:        case IFREG:
                    145:        case IFDIR:
                    146:                fread (ip, iop);
                    147:                break;
                    148: 
                    149:        case IFPIPE:
                    150:                pread (ip, iop);
                    151:                break;
                    152: 
                    153:        default:
                    154:                u.u_error = ENXIO;
                    155:                break;
                    156:        }
                    157: }
                    158: 
                    159: /*
                    160:  * Write to a file described by an inode and io structure.
                    161:  */
                    162: iwrite(ip, iop)
                    163: register INODE *ip;
                    164: register IO *iop;
                    165: {
                    166:        imod (ip);      /* write - mtime */
                    167:        icrt (ip);      /* write - ctime */
                    168:        if (iop->io_ioc == 0)
                    169:                return;
                    170: 
                    171:        switch (ip->i_mode & IFMT) {
                    172:        case IFCHR:
                    173:                dwrite (ip->i_a.i_rdev, iop);
                    174:                break;
                    175: 
                    176:        case IFBLK:
                    177:                fwrite (ip, iop);
                    178:                break;
                    179: 
                    180:        case IFREG:
                    181:        case IFDIR:
                    182:                if (getment (ip->i_dev, 1) == NULL)
                    183:                        return;
                    184:                fwrite (ip, iop);
                    185:                break;
                    186: 
                    187:        case IFPIPE:
                    188:                pwrite (ip, iop);
                    189:                break;
                    190: 
                    191:        default:
                    192:                u.u_error = ENXIO;
                    193:                break;
                    194:        }
                    195: }
                    196: 
                    197: /*
                    198:  * Given a block number, `b', store the offsets for the indirect blocks
                    199:  * backwards in the array, `lp', and return a pointer just after the
                    200:  * position where the first offset is stored.
                    201:  */
                    202: 
                    203: static int *
                    204: lmap (b, lp, numblocks)
                    205: register daddr_t b;
                    206: register int *lp;
                    207: int          * numblocks;
                    208: {
                    209:        register int n;
                    210: 
                    211:        if ((n = ND - b) > 0) {
                    212:                /*
                    213:                 * Just the one direct block, and further blocks up to the end
                    214:                 * of the block list in the inode.
                    215:                 */
                    216:                * lp ++ = b;
                    217:                * numblocks = n;
                    218:                return lp;
                    219:        }
                    220:        b -= ND;
                    221: 
                    222:        /*
                    223:         * First, the initial indirect block, followed by as many further
                    224:         * layers of indirection as we need.
                    225:         */
                    226: 
                    227:        n = nbnrem (b);
                    228:        * numblocks = NBN - n;
                    229:        * lp ++ = n;
                    230: 
                    231:        if ((b = nbndiv (b)) == 0) {
                    232:                * lp ++ = ND;
                    233:                return lp;
                    234:        }
                    235: 
                    236: 
                    237: #if    NI > 1
                    238:        b --;   /* Make offset in next indirect block zero-based */
                    239: 
                    240:        * lp ++ = nbnrem (b);
                    241:        if ((b = nbndiv (b)) == 0) {
                    242:                * lp ++ = ND + 1;
                    243:                return lp;
                    244:        }
                    245: 
                    246: #if    NI > 2
                    247:        b --;   /* Make offset in next indirect block zero-based */
                    248: 
                    249:        * lp ++ = nbnrem (b);
                    250:        if ((b = nbndiv (b)) == 0) {
                    251:                * lp ++ = ND + 2;
                    252:                return lp;
                    253:        }
                    254: #endif
                    255: #endif
                    256:        SET_U_ERROR (EFBIG, "lmap");
                    257:        return NULL;
                    258: }
                    259: 
                    260: int    t_groupmode = 0;
                    261: 
                    262: /*
                    263:  * Convert the given virtual block to a physical block for the given inode.
                    264:  * If the block does not map onto a physical block because the file is sparse
                    265:  * but it does exist, 0 is returned.  If an error is encountered, -1 is
                    266:  * returned.
                    267:  */
                    268: 
                    269: static int
                    270: vmap (ip, lb, count, blocklist, allocflag)
                    271: register INODE *ip;
                    272: daddr_t                lb;
                    273: int            count;
                    274: daddr_t              * blocklist;
                    275: int            allocflag;
                    276: {
                    277:        daddr_t pb;
                    278:        int list [1 + NI];
                    279:        int             nblocks;
                    280:        daddr_t       * outlist;
                    281:        BUF           * buf;
                    282:        int           * lp;
                    283:        int             resid = count;
                    284: 
                    285: more:
                    286:        if ((lp = lmap (lb, list, & nblocks)) == NULL)
                    287:                return -1;
                    288: 
                    289:        if (nblocks > resid)
                    290:                nblocks = resid;
                    291:        resid -= nblocks;
                    292:        lb += nblocks;
                    293: 
                    294:        outlist = ip->i_a.i_addr;
                    295:        buf = NULL;
                    296: 
                    297:        while (-- lp != list) {
                    298:                if ((pb = outlist [* lp]) == 0) {
                    299:                        /*
                    300:                         * If an indirect block is not present, then this
                    301:                         * implies that at least the next "nblocks" leaf
                    302:                         * blocks are also not present.
                    303:                         */
                    304: 
                    305:                        do
                    306:                                * blocklist ++ = -1;
                    307:                        while (-- nblocks > 0);
                    308:                        goto done;
                    309:                }
                    310: 
                    311:                if (buf != NULL) {
                    312:                        brelease (buf);
                    313:                        candaddr (pb);
                    314:                }
                    315: 
                    316:                if ((buf = bread (ip->i_dev, pb, BUF_SYNC)) == NULL)
                    317:                        return -1;
                    318: 
                    319:                outlist = (daddr_t *) buf->b_vaddr;
                    320:        }
                    321: 
                    322:        do {
                    323:                if ((pb = outlist [list [0] ++]) == 0)
                    324:                        pb = -1;
                    325:                else if (buf != NULL)
                    326:                        candaddr (pb);
                    327:                * blocklist ++ = pb;
                    328:        } while (-- nblocks > 0);
                    329: 
                    330: done:
                    331:        if (buf != NULL)
                    332:                brelease (buf);
                    333: 
                    334:        if (t_groupmode && resid > 0)
                    335:                goto more;
                    336: 
                    337:        return count - resid;
                    338: }
                    339: 
                    340: int    t_readahead = 0;
                    341: #define        READGROUP       16              /*
                    342:                                         * Maximum # of blocks to read as a
                    343:                                         * single normal group.
                    344:                                         */
                    345: #define        READAHEAD       8               /*
                    346:                                         * Maximum # of blocks to read ahead.
                    347:                                         */
                    348: 
                    349: /*
                    350:  * Read from a regular or block special file.
                    351:  */
                    352: fread(ip, iop)
                    353: INODE *ip;
                    354: register IO *iop;
                    355: {
                    356:        register int    n;
                    357:        register unsigned i;
                    358:        register off_t res;
                    359:        register unsigned off;
                    360:        register dev_t dev;
                    361:        register daddr_t lbn;
                    362:        register daddr_t pbn;
                    363:        register daddr_t abn;
                    364:        register daddr_t zbn;
                    365:        register BUF *bp;
                    366:        register int blk;
                    367:        daddr_t         list [READGROUP + READAHEAD];
                    368:        int             do_readahead;
                    369: 
                    370:        if ((ip->i_mode & IFMT) == IFBLK) {
                    371:                blk = 1;
                    372:                dev = ip->i_a.i_rdev;
                    373:        } else {
                    374:                blk = 0;
                    375:                dev = ip->i_dev;
                    376:        }
                    377:        abn = 0;
                    378:        zbn = 0;
                    379:        lbn = blockn (iop->io_seek);
                    380:        off = blocko (iop->io_seek);
                    381: 
                    382:        /*
                    383:         * NIGEL: The commented-out code talks about a mysterious "unsigned
                    384:         * prob" which does not in reality exist. All this really wants to
                    385:         * do is pick the minimum of the remaining size and the requested
                    386:         * size.
                    387:         */
                    388: 
                    389: #if    0
                    390:        res = ip->i_size - iop->io_seek;
                    391: 
                    392:        if (blk != 0 || (res > 0 && res > iop->io_ioc)) 
                    393:                res = iop->io_ioc;      /* unsigned prob with io_ioc */
                    394:        if (res <= 0)
                    395:                return;
                    396: #endif
                    397: 
                    398:        if (blk)
                    399:                res = iop->io_ioc;
                    400:        else if ((res = ip->i_size - iop->io_seek) > iop->io_ioc)
                    401:                res = iop->io_ioc;
                    402: 
                    403:        if (res == 0)
                    404:                return;
                    405: 
                    406:        /*
                    407:         * NIGEL: Test whether we want readahead based on whether this access
                    408:         * immediately follows some previous access... this does not apply to
                    409:         * inodes made from pipes, because there readahead will make us seek
                    410:         * beyond the space that is legal (pipes store funky data where a
                    411:         * normal file has indirect block pointers).
                    412:         */
                    413: 
                    414:        if ((lbn == ip->i_lastblock + 1) && (ip->i_mode & IFMT) != IFPIPE) {
                    415:                if ((do_readahead = t_readahead) < 0)
                    416:                        do_readahead = 0;
                    417:        } else
                    418:                do_readahead = 0;
                    419: 
                    420:        do {
                    421:                if (lbn >= zbn) {
                    422:                        if ((n = blockn (res + BSIZE - 1) + do_readahead) >
                    423:                            __ARRAY_LENGTH (list))
                    424:                                n = __ARRAY_LENGTH (list);
                    425: 
                    426:                        ASSERT (n > do_readahead);
                    427: 
                    428:                        if (blk == 0 && (n = vmap (ip, lbn, n, list, 0)) < 0)
                    429:                                return;
                    430: 
                    431:                        abn = lbn;
                    432:                        for (i = 0, zbn = lbn ; i < n ; i ++, zbn ++) {
                    433:                                if (blk != 0)
                    434:                                        list [i] = pbn = zbn;
                    435:                                else if ((pbn = list [i]) == 0)
                    436:                                        continue;
                    437: 
                    438:                                if (t_readahead != -1)
                    439:                                        (void) bread (dev, pbn, BUF_ASYNC);
                    440:                        }
                    441:                }
                    442: 
                    443:                if (res < (n = BSIZE - off))
                    444:                        n = res;
                    445: 
                    446:                if ((pbn = list [lbn - abn]) < 0)
                    447:                        ioclear (iop, n);
                    448:                else {
                    449:                        if ((bp = bread (dev, pbn, BUF_SYNC)) == NULL)
                    450:                                return;
                    451:                        iowrite (iop, bp->b_vaddr + off, n);
                    452:                        brelease (bp);
                    453:                }
                    454: 
                    455:                if (u.u_error)
                    456:                        return;
                    457:                lbn ++;
                    458:                off = 0;
                    459:        } while ((res -= n) > 0);
                    460: 
                    461:        ip->i_lastblock = lbn - 1;
                    462: }
                    463: 
                    464: int    t_writemode = 0;
                    465: 
                    466: /*
                    467:  * Write to a regular or block special file.
                    468:  */
                    469: fwrite(ip, iop)
                    470: INODE *ip;
                    471: register IO *iop;
                    472: {
                    473:        register unsigned n;
                    474:        register unsigned off;
                    475:        register daddr_t lbn;
                    476:        register BUF *bp;
                    477:        register int blk;
                    478:        register int com;
                    479: 
                    480:        lbn = blockn(iop->io_seek);
                    481:        off = blocko(iop->io_seek);
                    482:        blk = (ip->i_mode & IFMT) == IFBLK;
                    483:        while (iop->io_ioc > 0) {
                    484:                n = BSIZE - off;
                    485:                n = iop->io_ioc > n ? n : iop->io_ioc;
                    486:                com = off == 0 && n == BSIZE;
                    487:                if (blk == 0)
                    488:                        bp = aread (ip, lbn, com);
                    489:                else {
                    490:                        if (com)
                    491:                                bp = bclaim (ip->i_a.i_rdev, lbn, BUF_SYNC);
                    492:                        else
                    493:                                bp = bread (ip->i_a.i_rdev, lbn, BUF_SYNC);
                    494:                }
                    495:                if (bp == NULL)
                    496:                        return;
                    497:                ioread (iop, bp->b_vaddr + off, n);
                    498:                bp->b_flag |= BFMOD;
                    499:                if (com && (ip->i_mode & IFMT) != IFPIPE) {
                    500:                        bwrite (bp, t_writemode);
                    501:                        if (t_writemode)
                    502:                                brelease (bp);
                    503:                } else
                    504:                        brelease (bp);
                    505:                if (u.u_error)
                    506:                        return;
                    507:                lbn ++;
                    508:                off = 0;
                    509:                if ((iop->io_seek += n) > ip->i_size)
                    510:                        if (blk == 0)
                    511:                                ip->i_size = iop->io_seek;
                    512:        }
                    513: }
                    514: 
                    515: /*
                    516:  * Given an inode pointer, read the requested virtual block and return
                    517:  * a buffer with the data.
                    518:  */
                    519: BUF *
                    520: vread(ip, lb)
                    521: register INODE *ip;
                    522: daddr_t lb;
                    523: {
                    524:        daddr_t         pb;
                    525:        register BUF *bp;
                    526: 
                    527:        if (vmap (ip, lb, 1, & pb, 0) < 0)
                    528:                return NULL;
                    529:        if (pb != -1)
                    530:                return bread (ip->i_dev, pb, BUF_SYNC);
                    531:        bp = bclaim (NODEV, (daddr_t) 0, BUF_SYNC);
                    532:        kclear (bp->b_vaddr, BSIZE);
                    533:        return bp;
                    534: }
                    535: 
                    536: /*
                    537:  * Given an inode pointer, read the requested virtual block and return a
                    538:  * buffer with the data.  In sparse files, the necessary blocks are allocated.
                    539:  * If the flag, `fflag' is set, the final buffer is just claimed rather than
                    540:  * read as we are going to change it's contents completely.
                    541:  */
                    542: 
                    543: BUF *
                    544: aread (ip, lb, fflag)
                    545: register INODE *ip;
                    546: daddr_t lb;
                    547: {
                    548:        register BUF *bp;
                    549:        register int *lp;
                    550:        register dev_t dev;
                    551:        register int l;
                    552:        register int aflag;
                    553:        register int lflag;
                    554:        daddr_t * dp;
                    555:        daddr_t pb;
                    556:        int list[1+NI];
                    557:        int             nblocks;
                    558: 
                    559:        if ((lp = lmap (lb, list, & nblocks)) == NULL)
                    560:                return (NULL);
                    561:        aflag = 0;
                    562:        dev = ip->i_dev;
                    563:        pb = ip->i_a.i_addr [l = * -- lp];
                    564:        if (pb == 0) {
                    565:                aflag = 1;
                    566:                if ((pb = balloc (dev)) == 0)
                    567:                        return NULL;
                    568:                ip->i_a.i_addr [l] = pb;
                    569:        }
                    570:        for (;;) {
                    571:                lflag = lp == list;
                    572:                /*
                    573:                 * If we are not allocating a new block and the caller is
                    574:                 * going to preserve any of the data that we are going to
                    575:                 * return, then read in the previous block contents.
                    576:                 */
                    577:                if (! (aflag || (fflag && lflag))) {
                    578:                        if ((bp = bread (dev, pb, BUF_SYNC)) == NULL)
                    579:                                return NULL;
                    580:                } else {
                    581:                        bp = bclaim (dev, pb, BUF_SYNC);
                    582: 
                    583:                        /*
                    584:                         * If this is the last block and the caller is just
                    585:                         * going to overwrite it, don't zero-fill.
                    586:                         */
                    587: 
                    588:                        if (! (fflag && lflag))
                    589:                                kclear (bp->b_vaddr, BSIZE);
                    590:                        bp->b_flag |= BFMOD;
                    591:                }
                    592:                if (lflag)
                    593:                        return bp;
                    594: 
                    595:                aflag = 0;
                    596:                dp = bp->b_vaddr;
                    597:                pb = dp [l = * -- lp];
                    598:                candaddr (pb);
                    599:                if (pb == 0) {
                    600:                        aflag = 1;
                    601:                        if ((pb = balloc (dev)) == 0) {
                    602:                                brelease(bp);
                    603:                                return (NULL);
                    604:                        }
                    605:                        dp [l] = pb;
                    606:                        candaddr (dp [l]);
                    607:                        bp->b_flag |= BFMOD;
                    608:                }
                    609:                brelease (bp);
                    610:        }
                    611: }

unix.superglobalmegacorp.com

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