Annotation of researchv10no/sys/fs/alloc.c, revision 1.1

1.1     ! root        1: #include "sys/param.h"
        !             2: #include "sys/systm.h"
        !             3: #include "sys/filsys.h"
        !             4: #include "sys/fblk.h"
        !             5: #include "sys/buf.h"
        !             6: #include "sys/inode.h"
        !             7: #include "sys/ino.h"
        !             8: #include "sys/user.h"
        !             9: 
        !            10: typedef        struct fblk *FP;
        !            11: 
        !            12: /*
        !            13:  * alloc will obtain the next available
        !            14:  * free disk block from the free list of
        !            15:  * the specified filsys.
        !            16:  * The super block has up to NICFREE remembered
        !            17:  * free blocks; the last of these is read to
        !            18:  * obtain NICFREE more . . .
        !            19:  */
        !            20: static daddr_t bitfsalloc(), oldfsalloc(), bigfsalloc();
        !            21: 
        !            22: struct buf *
        !            23: alloc(fip, prev)
        !            24: struct inode *fip;
        !            25: daddr_t prev;
        !            26: {
        !            27:        daddr_t bno;
        !            28:        register struct filsys *fp;
        !            29:        register struct buf *bp;
        !            30: 
        !            31:        fp = getfs(fip);
        !            32:        while (fp->s_flock)
        !            33:                sleep((caddr_t)&fp->s_flock, PINOD);
        !            34:        if(BITFS(fip->i_dev))   /* unfortunately device dependent */
        !            35:                if(fp->U.N.S_flag)
        !            36:                        bno = bigfsalloc(fp, prev);
        !            37:                else
        !            38:                        bno = bitfsalloc(fp, prev);
        !            39:        else
        !            40:                bno = oldfsalloc(fp, fip->i_dev);
        !            41:        if (bno == 0) {
        !            42:                /*fp->s_nfree = 0;      /* but it would be wrong FIX*/
        !            43:                fp->s_tfree = 0;
        !            44:                fserr(fip->i_dev, fp, "file system full");
        !            45:                tsleep((caddr_t)&u, PRIBIO, 5); /* slow things down */
        !            46:                u.u_error = ENOSPC;
        !            47:                return (NULL);
        !            48:        }
        !            49:        bp = getblk(fip->i_dev, bno);
        !            50:        clrbuf(bp);
        !            51:        fp->s_fmod = 1;
        !            52:        fp->s_tfree--;
        !            53:        return (bp);
        !            54: }
        !            55: 
        !            56: /*
        !            57:  * bitmap fs alloc:
        !            58:  * given the previous block in the file,
        !            59:  * try to pick one in the same cylinder,
        !            60:  * preferably in a nice rotational place
        !            61:  * if we can't, pick one in the next couple of cylinders
        !            62:  * if we can't, just pick any block
        !            63:  */
        !            64: 
        !            65: static daddr_t
        !            66: bitfsalloc(fp, prev)
        !            67: register struct filsys *fp;
        !            68: daddr_t prev;
        !            69: {
        !            70:        register daddr_t bno;
        !            71:        register long i;
        !            72:        daddr_t cyl, end, best;
        !            73: 
        !            74:        best = -1;
        !            75:        if (fp->s_cylsize == 0) {       /* safety for the root.  ugh. */
        !            76:                fp->s_cylsize = 40;
        !            77:                fp->s_aspace = 4;       /* good for comets */
        !            78:        }
        !            79:        if (prev >= fp->s_isize) {
        !            80:                bno = prev / fp->s_cylsize;
        !            81:                bno *= fp->s_cylsize;
        !            82:                if (bno < fp->s_isize)
        !            83:                        bno = fp->s_isize;
        !            84:                cyl = bno + fp->s_cylsize;
        !            85:                end = bno + 3 * fp->s_cylsize;
        !            86:                if (end > fp->s_fsize)
        !            87:                        end = fp->s_fsize;
        !            88:                if (cyl > fp->s_fsize)
        !            89:                        cyl = fp->s_fsize;
        !            90:                i = bno - fp->s_isize;
        !            91:                best = findbit(fp->s_bfree, i, cyl-fp->s_isize, prev-fp->s_isize,
        !            92:                        fp->s_aspace);  /* in same cylinder */
        !            93:                if(best == -1)
        !            94:                        best = findbit(fp->s_bfree, cyl-fp->s_isize,
        !            95:                                end-fp->s_isize, 0L, 0);
        !            96:        }
        !            97:        if(best == -1)
        !            98:                best = findbit(fp->s_bfree, 0L, fp->s_fsize-fp->s_isize, 0L, 0);
        !            99:        if(best == -1)
        !           100:                return(0);
        !           101:        BITALLOC(fp->s_bfree, best);
        !           102:        if (fp->s_valid) {
        !           103:                fp->s_valid = 0;
        !           104:                update();               /* ugh */
        !           105:        }
        !           106:        return (best+fp->s_isize);
        !           107: }
        !           108: 
        !           109: /*
        !           110:  * new-style, multi-segment bitmap
        !           111:  * take care not to cross segment boundaries
        !           112:  */
        !           113: 
        !           114: static daddr_t
        !           115: bigfsalloc(fp, prev)
        !           116: register struct filsys *fp;
        !           117: daddr_t prev;
        !           118: {
        !           119:        register int fblk;
        !           120:        register long bs;
        !           121:        register long best, beg, cyl;
        !           122:        int nblk;
        !           123: 
        !           124:        bs = fp->U.N.S_bsize;
        !           125:        if(prev > 0) {
        !           126:                beg = prev/fp->s_cylsize;
        !           127:                beg *= fp->s_cylsize;
        !           128:                if(beg < fp->s_isize)
        !           129:                        beg = fp->s_isize;      /* unnecessary */
        !           130:                cyl = beg + fp->s_cylsize;
        !           131:                if(cyl > fp->s_fsize)
        !           132:                        cyl = fp->s_fsize;
        !           133:                fblk = beg/bs;
        !           134:                if (fblk != (cyl-1)/bs)
        !           135:                        cyl = (fblk+1)*bs;      /* bound to this block */
        !           136:                best = findbit(fp->U.N.S_blk[fblk]->b_un.b_words, beg%bs,
        !           137:                        cyl%bs, prev%bs, fp->s_aspace);
        !           138:                if (best != -1)
        !           139:                        goto done;
        !           140:                beg = cyl;
        !           141:                cyl = beg + 2 * fp->s_cylsize;
        !           142:                if (cyl >= fp->s_fsize)
        !           143:                        cyl = fp->s_fsize;
        !           144:                fblk = beg/bs;
        !           145:                if (fblk != (cyl - 1)/bs)
        !           146:                        cyl = (fblk+1)*bs;
        !           147:                best = findbit(fp->U.N.S_blk[fblk]->b_un.b_words, beg%bs,
        !           148:                        cyl%bs, 0L, 0);
        !           149:                if(best != -1)
        !           150:                        goto done;
        !           151:        }
        !           152:        /*
        !           153:         * find any free bit at all
        !           154:         */
        !           155:        nblk = (fp->s_fsize + bs - 1) / bs;
        !           156:        for (fblk = 0; fblk < nblk; fblk++) {
        !           157:                best = findbit(fp->U.N.S_blk[fblk]->b_un.b_words, 0L, bs, 0L, 0);
        !           158:                if(best != -1)
        !           159:                        goto done;
        !           160:        }
        !           161:        /*
        !           162:         * found nothing nowhere
        !           163:         */
        !           164:        return(0);
        !           165:        /*
        !           166:         * found bit best in block fblk
        !           167:         */
        !           168: done:
        !           169:        BITALLOC((fp->U.N.S_blk[fblk]->b_un.b_words), best);
        !           170:        if(fp->s_valid) {
        !           171:                fp->s_valid = 0;
        !           172:                update();
        !           173:        }
        !           174:        return(best+fblk*bs);
        !           175: }
        !           176: 
        !           177: /* find a bit between bot and top, preferably at least space from prev */
        !           178: findbit(ptr, bot, top, prev, space)
        !           179: long *ptr;
        !           180: long bot, top, prev;
        !           181: {
        !           182:        register long *p;
        !           183:        register int j;
        !           184:        register long bno, best;
        !           185: 
        !           186:        best = -1;
        !           187:        j = bot/BITCELL;
        !           188:        p = ptr + j;
        !           189:        bno = j*BITCELL;        /* start on long boundary */
        !           190:        for(; bno < top; p++) {
        !           191:                if(*p == 0) {   /* none free in whole long */
        !           192:                        bno += BITCELL; /* so onward */
        !           193:                        continue;
        !           194:                }
        !           195:                for(j = 0; j < BITCELL; j++, bno++) {
        !           196:                        if((*p & (1<<j)) == 0)
        !           197:                                continue;
        !           198:                        if(bno < bot || bno >= top)     /* out of the loop? */
        !           199:                                continue;       /* first and last longs */
        !           200:                        if(best == -1)
        !           201:                                best = bno;
        !           202:                        if(bno - prev >= space)
        !           203:                                return(bno);
        !           204:                }
        !           205:        }
        !           206:        return(best);   /* -1 or whatever we found */
        !           207: }
        !           208: 
        !           209: static daddr_t
        !           210: oldfsalloc(fp, dev)
        !           211: register struct filsys *fp;
        !           212: {
        !           213:        register daddr_t bno;
        !           214:        register struct buf *bp;
        !           215: 
        !           216:        do {
        !           217:                if (fp->s_nfree <= 0)
        !           218:                        return (0);
        !           219:                if (fp->s_nfree > NICFREE) {
        !           220:                        fserr(dev, fp, "bad free count");
        !           221:                        return (0);
        !           222:                }
        !           223:                bno = fp->s_free[--fp->s_nfree];
        !           224:                if (bno == 0)
        !           225:                        return (0);
        !           226:        } while (badblock(dev, fp, bno));
        !           227:        if (fp->s_nfree <= 0) {
        !           228:                fp->s_flock++;
        !           229:                bp = bread(dev, bno);
        !           230:                if ((bp->b_flags&B_ERROR) == 0) {
        !           231:                        fp->s_nfree = ((FP)(bp->b_un.b_addr))->df_nfree;
        !           232:                        bcopy((caddr_t)((FP)(bp->b_un.b_addr))->df_free,
        !           233:                            (caddr_t)fp->s_free, sizeof(fp->s_free));
        !           234:                }
        !           235:                brelse(bp);
        !           236:                fp->s_flock = 0;
        !           237:                wakeup((caddr_t)&fp->s_flock);
        !           238:                if (fp->s_nfree <= 0)
        !           239:                        return (0);
        !           240:        }
        !           241:        return (bno);
        !           242: }
        !           243: 
        !           244: /*
        !           245:  * place the specified disk block
        !           246:  * back on the free list of the
        !           247:  * specified device.
        !           248:  */
        !           249: free(fip, bno)
        !           250:        struct inode *fip;
        !           251:        daddr_t bno;
        !           252: {      int bs;
        !           253:        register struct filsys *fp;
        !           254:        register struct buf *bp;
        !           255: 
        !           256:        fp = getfs(fip);
        !           257:        fp->s_fmod = 1;
        !           258:        while (fp->s_flock)
        !           259:                sleep((caddr_t)&fp->s_flock, PINOD);
        !           260:        if (badblock(fip->i_dev, fp, bno))
        !           261:                return;
        !           262:        if(BITFS(fip->i_dev)) {
        !           263:        /* paranoia suggests checking it's not already free */
        !           264:                if(fp->U.N.S_flag) {
        !           265:                        bs = fp->U.N.S_bsize;
        !           266:                        BITFREE((fp->U.N.S_blk[bno/bs]->b_un.b_words), bno%bs);
        !           267:                }
        !           268:                else {
        !           269:                        bno -= fp->s_isize;
        !           270:                        BITFREE(fp->s_bfree, bno);
        !           271:                }
        !           272:                if(fp->s_valid) {       /* not any more */
        !           273:                        fp->s_valid = 0;
        !           274:                        update();       /* even GROSSER */
        !           275:                }
        !           276:        }
        !           277:        else {
        !           278:                if (fp->s_nfree <= 0) {
        !           279:                        fp->s_nfree = 1;
        !           280:                        fp->s_free[0] = 0;
        !           281:                }
        !           282:                if (fp->s_nfree >= NICFREE) {
        !           283:                        fp->s_flock++;
        !           284:                        bp = getblk(fip->i_dev, bno);
        !           285:                        ((FP)(bp->b_un.b_addr))->df_nfree = fp->s_nfree;
        !           286:                        bcopy((caddr_t)fp->s_free,
        !           287:                            (caddr_t)((FP)(bp->b_un.b_addr))->df_free,
        !           288:                            sizeof(fp->s_free));
        !           289:                        fp->s_nfree = 0;
        !           290:                        bwrite(bp);
        !           291:                        fp->s_flock = 0;
        !           292:                        wakeup((caddr_t)&fp->s_flock);
        !           293:                }
        !           294:                fp->s_free[fp->s_nfree++] = bno;
        !           295:        }
        !           296:        fp->s_tfree++;
        !           297:        fp->s_fmod = 1;
        !           298: }
        !           299: 
        !           300: /*
        !           301:  * Check that a block number is in the
        !           302:  * range between the I list and the size
        !           303:  * of the device.
        !           304:  * This is used mainly to check that a
        !           305:  * garbage file system has not been mounted.
        !           306:  */
        !           307: badblock(dev, fp, bn)
        !           308:        dev_t dev;
        !           309:        register struct filsys *fp;
        !           310:        daddr_t bn;
        !           311: {
        !           312: 
        !           313:        if (bn < fp->s_isize || bn >= fp->s_fsize) {
        !           314:                fserr(dev, fp, "bad block");
        !           315:                return(1);
        !           316:        }
        !           317:        return(0);
        !           318: }
        !           319: 
        !           320: /*
        !           321:  * allocate an unused disk inode in the specified filesystem
        !           322:  * up to NICINOD possible i-numbers are kept in a list
        !           323:  * in s_inode; try those first.  If the list empties,
        !           324:  * scan the i-list and fill it again.
        !           325:  * To speed things up, pick up the scan where it last
        !           326:  * left off (s_lasti) unless there are believed to be
        !           327:  * many free i-nodes with lower numbers (s_nbehind).
        !           328:  * s_ilock is there only to avoid having two processes
        !           329:  * in the list-filling code.
        !           330:  */
        !           331: 
        !           332: int dupinod;           /* debug */
        !           333: 
        !           334: struct inode *
        !           335: ialloc(fip)
        !           336:        struct inode *fip;
        !           337: {
        !           338:        register struct filsys *fp;
        !           339:        register struct buf *bp;
        !           340:        register struct inode *ip;
        !           341:        register int i;
        !           342:        struct dinode *dp;
        !           343:        ino_t ino;
        !           344:        int first;
        !           345:        int inopb;
        !           346:        daddr_t adr;
        !           347: 
        !           348:        fp = getfs(fip);
        !           349:        if (fp->s_ninode > NICINOD || fp->s_ninode < 0) {
        !           350:                fserr(fip->i_dev, fp, "bad inode count");
        !           351:                fp->s_ninode = 0;
        !           352:        }
        !           353: loop:
        !           354:        if (fp->s_ninode > 0) {
        !           355:                ino = fp->s_inode[--fp->s_ninode];
        !           356:                if (ifind(fip, ino)) {  /* already in use */
        !           357:                        dupinod++;      /* debug */
        !           358:                        goto loop;
        !           359:                }
        !           360:                ip = iget(fip, fip->i_dev, ino);
        !           361:                if (ip == NULL)         /* probably table full */
        !           362:                        return(NULL);
        !           363:                if (ip->i_count == 1 && fsiread(fip, ip) < 0)
        !           364:                        goto loop;
        !           365:                if (ip->i_mode != 0) {  /* already allocated */
        !           366:                        iput(ip);
        !           367:                        goto loop;
        !           368:                }
        !           369:                for (i=0; i<NADDR; i++)
        !           370:                        ip->i_un.i_addr[i] = 0;
        !           371:                fp->s_tinode--;
        !           372:                fp->s_fmod = 1;
        !           373:                return(ip);
        !           374:        }
        !           375:        /*
        !           376:         * nothing left in super-block; restock
        !           377:         */
        !           378:        while (fp->s_ilock)
        !           379:                sleep((caddr_t)&fp->s_ilock, PINOD);
        !           380:        if (fp->s_ninode > 0)   /* someone beat us to it? */
        !           381:                goto loop;
        !           382:        fp->s_ilock++;
        !           383:        first = 1;
        !           384:        inopb = INOPB(fip->i_dev);      /* optimization */
        !           385: fromtop:
        !           386:        ino = fp->s_lasti;
        !           387:        ino = ((ino / inopb) * inopb) + 1;      /* round down to start of block */
        !           388:        adr = itod(fip->i_dev, ino);
        !           389:        if (fp->s_nbehind > 4 * NICINOD
        !           390:        ||  adr <= SUPERB || adr >= fp->s_isize
        !           391:        ||  first == 0) {
        !           392:                first = 0;
        !           393:                ino = 1;
        !           394:                adr = SUPERB + 1;
        !           395:                fp->s_nbehind = 0;
        !           396:        }
        !           397:        for(; adr < fp->s_isize; adr++) {
        !           398:                bp = bread(fip->i_dev, adr);
        !           399:                if (bp->b_flags & B_ERROR) {
        !           400:                        brelse(bp);
        !           401:                        ino += inopb;
        !           402:                        continue;
        !           403:                }
        !           404:                dp = bp->b_un.b_dino;
        !           405:                for (i=0; i<inopb; i++, ino++, dp++) {
        !           406:                        if (dp->di_mode != 0 || ifind(fip, ino))
        !           407:                                continue;
        !           408:                        fp->s_inode[fp->s_ninode++] = ino;
        !           409:                        if (fp->s_ninode >= NICINOD)
        !           410:                                break;
        !           411:                }
        !           412:                brelse(bp);
        !           413:                if (fp->s_ninode >= NICINOD)
        !           414:                        break;
        !           415:        }
        !           416:        /*
        !           417:         * if we found nothing,
        !           418:         * try again from the beginning of the i-list
        !           419:         */
        !           420:        if (fp->s_ninode <= 0 && first) {
        !           421:                first = 0;
        !           422:                goto fromtop;
        !           423:        }
        !           424:        if (fp->s_ninode == NICINOD)
        !           425:                fp->s_lasti = ino;
        !           426:        else {          /* hit the end, but found something */
        !           427:                fp->s_lasti = 1;
        !           428:                fp->s_nbehind = 0;
        !           429:        }
        !           430:        fp->s_ilock = 0;
        !           431:        wakeup((caddr_t)&fp->s_ilock);
        !           432:        if (fp->s_ninode > 0)
        !           433:                goto loop;
        !           434:        fserr(fip->i_dev, fp, "out of inodes");
        !           435:        u.u_error = ENOSPC;
        !           436:        return (NULL);
        !           437: }
        !           438: 
        !           439: /*
        !           440:  * Free the specified inode on the specified device.
        !           441:  * The algorithm stores up to NICINOD inodes in the super
        !           442:  * block and throws away any more.  It keeps track of the
        !           443:  * number of inodes thrown away which preceded the current
        !           444:  * search point in the file system.  This lets us rescan
        !           445:  * for more inodes from the beginning only when there
        !           446:  * are a reasonable number of inodes back there to reallocate.
        !           447:  */
        !           448: 
        !           449: ifree(ip)
        !           450: register struct inode *ip;
        !           451: {
        !           452:        register struct filsys *fp;
        !           453: 
        !           454:        fp = getfs(ip);
        !           455:        if (fp->s_ninode > NICINOD || fp->s_ninode < 0) {
        !           456:                fserr(ip->i_dev, fp, "bad inode count");
        !           457:                fp->s_ninode = 0;
        !           458:        }
        !           459:        fp->s_tinode++;
        !           460:        if (fp->s_ilock)
        !           461:                return;
        !           462:        if (fp->s_ninode >= NICINOD) {
        !           463:                if (fp->s_lasti > ip->i_number)
        !           464:                        fp->s_nbehind++;
        !           465:                return;
        !           466:        }
        !           467:        fp->s_inode[fp->s_ninode++] = ip->i_number;
        !           468:        fp->s_fmod = 1;
        !           469: }
        !           470: 
        !           471: /*
        !           472:  * getfs maps an inode into
        !           473:  * a pointer to the incore super
        !           474:  * block.
        !           475:  *
        !           476:  * panic: no fs -- the device is not mounted.
        !           477:  *     this "cannot happen"
        !           478:  */
        !           479: struct filsys *
        !           480: getfs(fip)
        !           481: register struct inode *fip;
        !           482: {
        !           483: 
        !           484:        if (fip->i_fstyp != 0 || fip->i_un.i_bufp == NULL)
        !           485:                panic("no fs");
        !           486:        return (fip->i_un.i_bufp->b_un.b_filsys);
        !           487: }
        !           488: 
        !           489: /*
        !           490:  * Fserr prints the name of a file system
        !           491:  * with an error diagnostic, in the form
        !           492:  *     filsys: error message
        !           493:  */
        !           494: fserr(dev, fp, cp)
        !           495:        dev_t dev;
        !           496:        struct filsys *fp;
        !           497:        char *cp;
        !           498: {
        !           499: 
        !           500:        printf("0%o,0%o %s: %s\n", major(dev), minor(dev), fp->s_fsmnt, cp);
        !           501: }
        !           502: 
        !           503: /*
        !           504:  * Update is the internal name of 'sync'.  It goes through the disk
        !           505:  * queues to initiate sandbagged IO; goes through the inodes to write
        !           506:  * modified nodes; and it goes through the mount table to initiate modified
        !           507:  * super blocks.
        !           508:  */
        !           509: update()
        !           510: {
        !           511:        register struct inode *ip;
        !           512:        static int updlock;
        !           513: 
        !           514:        if (updlock)
        !           515:                return;
        !           516:        updlock++;
        !           517:        /*
        !           518:         * Write back each (modified) inode.
        !           519:         */
        !           520:        for (ip = inode; ip < inodeNINODE; ip++)
        !           521:                if((ip->i_flag&ILOCK)==0 && ip->i_count) {
        !           522:                        ip->i_flag |= ILOCK;
        !           523:                        ip->i_count++;
        !           524:                        iupdat(ip, &time, &time, 0);
        !           525:                        iput(ip);
        !           526:                }
        !           527:        updlock = 0;
        !           528:        /*
        !           529:         * Force stale buffer cache information to be flushed,
        !           530:         * for all devices.
        !           531:         */
        !           532:        bflush(NODEV);
        !           533: }

unix.superglobalmegacorp.com

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