Annotation of coherent/b/STREAMS/coh.386/fs3.c, revision 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.