Annotation of researchv9/sys.vax/sys/alloc.c, revision 1.1

1.1     ! root        1: /*     alloc.c 4.8     81/03/08        */
        !             2: 
        !             3: #include "../h/param.h"
        !             4: #include "../h/systm.h"
        !             5: #include "../h/mount.h"
        !             6: #include "../h/filsys.h"
        !             7: #include "../h/fblk.h"
        !             8: #include "../h/conf.h"
        !             9: #include "../h/buf.h"
        !            10: #include "../h/inode.h"
        !            11: #include "../h/ino.h"
        !            12: #include "../h/dir.h"
        !            13: #include "../h/user.h"
        !            14: #include "../h/trace.h"
        !            15: typedef        struct fblk *FP;
        !            16: 
        !            17: /*
        !            18:  * alloc will obtain the next available
        !            19:  * free disk block from the free list of
        !            20:  * the specified filsys.
        !            21:  * The super block has up to NICFREE remembered
        !            22:  * free blocks; the last of these is read to
        !            23:  * obtain NICFREE more . . .
        !            24:  */
        !            25: struct buf *
        !            26: alloc(fip, prev)
        !            27: struct inode *fip;
        !            28: daddr_t prev;
        !            29: {
        !            30:        daddr_t bno;
        !            31:        register struct filsys *fp;
        !            32:        register struct buf *bp;
        !            33:        register int i, j;
        !            34:        register long *p;
        !            35: 
        !            36:        fp = getfs(fip);
        !            37:        while (fp->s_flock)
        !            38:                sleep((caddr_t)&fp->s_flock, PINOD);
        !            39:        if(BITFS(fip->i_dev)) { /* unfortunately device dependent */
        !            40:        /* this code is UGLY, fix it */
        !            41:                if(prev < fp->s_isize)
        !            42:                        goto scan;
        !            43:                /* try for an acceptable free block in next
        !            44:                 * three cylinders, then start over at the beginning */
        !            45:                bno = 0;
        !            46:                j = prev/(4*10);
        !            47:                j *= 4 * 10;
        !            48:                if(j < fp->s_isize)
        !            49:                        j = fp->s_isize;
        !            50:                j -= fp->s_isize;
        !            51:                for(i = 0; i < 3 * 4 * 10; i++, j++) {
        !            52:                        if(j >= fp->s_fsize - fp->s_isize)
        !            53:                                break;
        !            54:                        if(!(fp->s_bfree[j>>5] & (1 << (j&31))))
        !            55:                                continue;
        !            56:                        /* same cylinder? */
        !            57:                        if((j+fp->s_isize)/(4*10) != prev/(4*10)) {     /* take best */
        !            58:                                if(bno == 0)
        !            59:                                        bno = j;
        !            60:                                fp->s_bfree[bno>>5] &= ~(1 << (bno&31));
        !            61:                                bno += fp->s_isize;
        !            62:                                goto found;
        !            63:                        }
        !            64:                        bno = j;
        !            65:                        p = fp->s_bfree + (j>>5);
        !            66:                        /* same sector or next, continue */
        !            67:                        if((j+fp->s_isize)%4 != prev%4 && (j+fp->s_isize)%4 != (prev+1)%4) {
        !            68:                                *p &= ~(1 << (j&31));
        !            69:                                bno += fp->s_isize;
        !            70:                                goto found;
        !            71:                        }
        !            72:                }
        !            73:                /* did we find anything? */
        !            74:                if(bno != 0) {
        !            75:                        fp->s_bfree[bno>>5] &= ~(1 << (bno&31));
        !            76:                        bno += fp->s_isize;
        !            77:                        goto found;
        !            78:                }
        !            79: scan:
        !            80:                p = fp->s_bfree;
        !            81:                for(i = 0; i < BITMAP && !*p; i++, p++)
        !            82:                        ;
        !            83:                if(i >= BITMAP)
        !            84:                        goto nospace;
        !            85:                bno = fp->s_isize + 32 * i;
        !            86:                for(j = 0; j < 32; j++) /* BITS PER LONG */
        !            87:                        if(*p & (1 << j))
        !            88:                                break;
        !            89:                if(j >= 32)
        !            90:                        panic("alloc bitmap");
        !            91:                bno += j;
        !            92:                if(bno >= fp->s_fsize)
        !            93:                        goto nospace;
        !            94:                *p &= ~(1 << j);
        !            95:                if(fp->s_valid) {       /* was valid, isn't anymore */
        !            96:                        fp->s_valid = 0;
        !            97:                        update();       /* GROSS, but safe */
        !            98:                }
        !            99:        }
        !           100:        else {
        !           101:                do {
        !           102:                        if (fp->s_nfree <= 0)
        !           103:                                goto nospace;
        !           104:                        if (fp->s_nfree > NICFREE) {
        !           105:                                fserr(fp, "bad free count");
        !           106:                                goto nospace;
        !           107:                        }
        !           108:                        bno = fp->s_free[--fp->s_nfree];
        !           109:                        if (bno == 0)
        !           110:                                goto nospace;
        !           111:                } while (badblock(fp, bno));
        !           112:                if (fp->s_nfree <= 0) {
        !           113:                        fp->s_flock++;
        !           114:                        bp = bread(fip->i_dev, bno);
        !           115:                        if ((bp->b_flags&B_ERROR) == 0) {
        !           116:                                fp->s_nfree = ((FP)(bp->b_un.b_addr))->df_nfree;
        !           117:                                bcopy((caddr_t)((FP)(bp->b_un.b_addr))->df_free,
        !           118:                                    (caddr_t)fp->s_free, sizeof(fp->s_free));
        !           119:                        }
        !           120:                        brelse(bp);
        !           121:                        fp->s_flock = 0;
        !           122:                        wakeup((caddr_t)&fp->s_flock);
        !           123:                        if (fp->s_nfree <= 0)
        !           124:                                goto nospace;
        !           125:                }
        !           126:        }
        !           127: found:
        !           128:        bp = getblk(fip->i_dev, bno);
        !           129:        clrbuf(bp);
        !           130:        fp->s_fmod = 1;
        !           131:        fp->s_tfree--;
        !           132:        return (bp);
        !           133: 
        !           134: nospace:
        !           135:        fp->s_nfree = 0;
        !           136:        fp->s_tfree = 0;
        !           137:        fserr(fp, "file system full");
        !           138:        /* THIS IS A KLUDGE... */
        !           139:        /* SHOULD RATHER SEND A SIGNAL AND SUSPEND THE PROCESS IN A */
        !           140:        /* STATE FROM WHICH THE SYSTEM CALL WILL RESTART */
        !           141:        uprintf("\n%s: write failed, file system is full\n", fp->s_fsmnt);
        !           142:        for (i = 0; i < 5; i++)
        !           143:                sleep((caddr_t)&lbolt, PRIBIO);
        !           144:        /* END KLUDGE */
        !           145:        u.u_error = ENOSPC;
        !           146:        return (NULL);
        !           147: }
        !           148: 
        !           149: /*
        !           150:  * place the specified disk block
        !           151:  * back on the free list of the
        !           152:  * specified device.
        !           153:  */
        !           154: free(fip, bno)
        !           155:        struct inode *fip;
        !           156:        daddr_t bno;
        !           157: {
        !           158:        register struct filsys *fp;
        !           159:        register struct buf *bp;
        !           160: 
        !           161:        fp = getfs(fip);
        !           162:        fp->s_fmod = 1;
        !           163:        while (fp->s_flock)
        !           164:                sleep((caddr_t)&fp->s_flock, PINOD);
        !           165:        if (badblock(fp, bno))
        !           166:                return;
        !           167:        if(BITFS(fip->i_dev)) {
        !           168:                bno -= fp->s_isize;
        !           169:                fp->s_bfree[bno/32] |= (1 << (bno % 32));
        !           170:                if(fp->s_valid) {       /* not any more */
        !           171:                        fp->s_valid = 0;
        !           172:                        update();       /* even GROSSER */
        !           173:                }
        !           174:        }
        !           175:        else {
        !           176:                if (fp->s_nfree <= 0) {
        !           177:                        fp->s_nfree = 1;
        !           178:                        fp->s_free[0] = 0;
        !           179:                }
        !           180:                if (fp->s_nfree >= NICFREE) {
        !           181:                        fp->s_flock++;
        !           182:                        bp = getblk(fip->i_dev, bno);
        !           183:                        ((FP)(bp->b_un.b_addr))->df_nfree = fp->s_nfree;
        !           184:                        bcopy((caddr_t)fp->s_free,
        !           185:                            (caddr_t)((FP)(bp->b_un.b_addr))->df_free,
        !           186:                            sizeof(fp->s_free));
        !           187:                        fp->s_nfree = 0;
        !           188:                        bwrite(bp);
        !           189:                        fp->s_flock = 0;
        !           190:                        wakeup((caddr_t)&fp->s_flock);
        !           191:                }
        !           192:                fp->s_free[fp->s_nfree++] = bno;
        !           193:        }
        !           194:        fp->s_tfree++;
        !           195:        fp->s_fmod = 1;
        !           196: }
        !           197: 
        !           198: /*
        !           199:  * Check that a block number is in the
        !           200:  * range between the I list and the size
        !           201:  * of the device.
        !           202:  * This is used mainly to check that a
        !           203:  * garbage file system has not been mounted.
        !           204:  */
        !           205: badblock(fp, bn)
        !           206:        register struct filsys *fp;
        !           207:        daddr_t bn;
        !           208: {
        !           209: 
        !           210:        if (bn < fp->s_isize || bn >= fp->s_fsize) {
        !           211:                fserr(fp, "bad block");
        !           212:                return(1);
        !           213:        }
        !           214:        return(0);
        !           215: }
        !           216: 
        !           217: /*
        !           218:  * Allocate an unused inode on the specified device.
        !           219:  * Used with file creation.  The algorithm keeps up to
        !           220:  * NICINOD spare inodes in the super block.  When this runs out,
        !           221:  * the inodes are searched to pick up more.  We keep searching
        !           222:  * foreward on the device, remembering the number of inodes
        !           223:  * which are freed behind our search point for which there is no
        !           224:  * room in the in-core table.  When this number passes a threshold
        !           225:  * (or if we search to the end of the ilist without finding any inodes)
        !           226:  * we restart the search from the beginning.
        !           227:  */
        !           228: 
        !           229: struct inode *
        !           230: ialloc(fip)
        !           231:        struct inode *fip;
        !           232: {
        !           233:        register struct filsys *fp;
        !           234:        register struct buf *bp;
        !           235:        register struct inode *ip;
        !           236:        register int i;
        !           237:        struct dinode *dp;
        !           238:        ino_t ino, inobas;
        !           239:        int first;
        !           240:        daddr_t adr;
        !           241: 
        !           242:        fp = getfs(fip);
        !           243:        while (fp->s_ilock)
        !           244:                sleep((caddr_t)&fp->s_ilock, PINOD);
        !           245:        fp->s_ilock++;
        !           246: loop:
        !           247:        if (fp->s_ninode > 0) {
        !           248:                ino = fp->s_inode[--fp->s_ninode];
        !           249:                ip = iget(fip, fip->i_dev, ino);
        !           250:                if (ip == NULL) {
        !           251:                        fp->s_ilock = 0;
        !           252:                        wakeup((caddr_t)&fp->s_ilock);
        !           253:                        return(NULL);
        !           254:                }
        !           255:                if (ip->i_mode == 0 && ip->i_number > ROOTINO) {
        !           256:                        for (i=0; i<NADDR; i++)
        !           257:                                ip->i_un.i_addr[i] = 0;
        !           258:                        fp->s_tinode--;
        !           259:                        fp->s_fmod = 1;
        !           260:                        fp->s_ilock = 0;
        !           261:                        wakeup((caddr_t)&fp->s_ilock);
        !           262:                        return(ip);
        !           263:                }
        !           264:                /*
        !           265:                 * Inode was allocated after all.
        !           266:                 * Look some more.
        !           267:                 */
        !           268:                iput(ip);
        !           269:                goto loop;
        !           270:        }
        !           271:        /*
        !           272:         * If less than 4*NICINOD inodes are known
        !           273:         * to be free behind the current search point,
        !           274:         * then search forward; else search from beginning.
        !           275:         */
        !           276:        if (fp->s_nbehind < 4 * NICINOD) {
        !           277:                first = 1;
        !           278:                ino = fp->s_lasti;
        !           279:                if(ino <= ROOTINO)
        !           280:                        goto fromtop;
        !           281:                if (itod(fip->i_dev, ino) >= fp->s_isize)
        !           282:                        panic("ialloc");
        !           283:                adr = itod(fip->i_dev, ino);
        !           284:        } else {
        !           285: fromtop:
        !           286:                first = 0;
        !           287:                ino = 1;
        !           288:                adr = SUPERB+1;
        !           289:                fp->s_nbehind = 0;
        !           290:        }
        !           291:        /*
        !           292:         * This is the search for free inodes.
        !           293:         */
        !           294:        for(; adr < fp->s_isize; adr++) {
        !           295:                inobas = ino;
        !           296:                bp = bread(fip->i_dev, adr);
        !           297:                if ((bp->b_flags&B_CACHE) == 0)
        !           298:                        u.u_vm.vm_inblk--;              /* no charge! */
        !           299:                if (bp->b_flags & B_ERROR) {
        !           300:                        brelse(bp);
        !           301:                        ino += INOPB(fip->i_dev);
        !           302:                        continue;
        !           303:                }
        !           304:                dp = bp->b_un.b_dino;
        !           305:                for (i=0; i<INOPB(fip->i_dev); i++, ino++, dp++) {
        !           306:                        if (dp->di_mode != 0 || ifind(fip, ino))
        !           307:                                continue;
        !           308:                        if (ino > ROOTINO)
        !           309:                                fp->s_inode[fp->s_ninode++] = ino;
        !           310:                        if (fp->s_ninode >= NICINOD)
        !           311:                                break;
        !           312:                }
        !           313:                brelse(bp);
        !           314:                if (fp->s_ninode >= NICINOD)
        !           315:                        break;
        !           316:        }
        !           317:        /*
        !           318:         * If the search didn't net a full superblock of inodes,
        !           319:         * then try it again from the beginning of the ilist.
        !           320:         */
        !           321:        if (fp->s_ninode < NICINOD && first)
        !           322:                goto fromtop;
        !           323:        fp->s_lasti = inobas;
        !           324:        fp->s_ilock = 0;
        !           325:        wakeup((caddr_t)&fp->s_ilock);
        !           326:        if (fp->s_ninode > 0)
        !           327:                goto loop;
        !           328:        fserr(fp, "out of inodes");
        !           329:        uprintf("\n%s: create failed, no inodes free\n", fp->s_fsmnt);
        !           330:        u.u_error = ENOSPC;
        !           331:        return (NULL);
        !           332: }
        !           333: 
        !           334: /*
        !           335:  * Free the specified inode on the specified device.
        !           336:  * The algorithm stores up to NICINOD inodes in the super
        !           337:  * block and throws away any more.  It keeps track of the
        !           338:  * number of inodes thrown away which preceded the current
        !           339:  * search point in the file system.  This lets us rescan
        !           340:  * for more inodes from the beginning only when there
        !           341:  * are a reasonable number of inodes back there to reallocate.
        !           342:  */
        !           343: 
        !           344: ifree(fip, ino)
        !           345:        struct inode *fip;
        !           346:        ino_t ino;
        !           347: {
        !           348:        register struct filsys *fp;
        !           349: 
        !           350:        if(ino <= ROOTINO)
        !           351:                return;
        !           352:        fp = getfs(fip);
        !           353:        fp->s_tinode++;
        !           354:        if (fp->s_ilock)
        !           355:                return;
        !           356:        if (fp->s_ninode >= NICINOD) {
        !           357:                if (fp->s_lasti > ino)
        !           358:                        fp->s_nbehind++;
        !           359:                return;
        !           360:        }
        !           361:        fp->s_inode[fp->s_ninode++] = ino;
        !           362:        fp->s_fmod = 1;
        !           363: }
        !           364: 
        !           365: /*
        !           366:  * getfs maps an inode into
        !           367:  * a pointer to the incore super
        !           368:  * block.
        !           369:  * A consistency check of the
        !           370:  * in core free-block and i-node
        !           371:  * counts is performed.
        !           372:  *
        !           373:  * panic: no fs -- the device is not mounted.
        !           374:  *     this "cannot happen"
        !           375:  */
        !           376: struct filsys *
        !           377: getfs(fip)
        !           378: register struct inode *fip;
        !           379: {
        !           380:        register struct filsys *fp;
        !           381: 
        !           382:        if (fip->i_fstyp != 0 || fip->i_un.i_bufp == NULL)
        !           383:                panic("no fs");
        !           384:        fp = fip->i_un.i_bufp->b_un.b_filsys;
        !           385:        if (fp->s_nfree > NICFREE || fp->s_ninode > NICINOD) {
        !           386:                fserr(fp, "bad count");
        !           387:                fp->s_nfree = 0;
        !           388:                fp->s_ninode = 0;
        !           389:        }
        !           390:        return(fp);
        !           391: }
        !           392: 
        !           393: /*
        !           394:  * Fserr prints the name of a file system
        !           395:  * with an error diagnostic, in the form
        !           396:  *     filsys: error message
        !           397:  */
        !           398: fserr(fp, cp)
        !           399:        struct filsys *fp;
        !           400:        char *cp;
        !           401: {
        !           402: 
        !           403:        printf("%s: %s\n", fp->s_fsmnt, cp);
        !           404: }
        !           405: 
        !           406: /*
        !           407:  * Getfsx returns the index in the file system
        !           408:  * table of the specified device.  The swap device
        !           409:  * is also assigned a pseudo-index.  The index may
        !           410:  * be used as a compressed indication of the location
        !           411:  * of a block, recording
        !           412:  *     <getfsx(dev),blkno>
        !           413:  * rather than
        !           414:  *     <dev, blkno>
        !           415:  * provided the information need remain valid only
        !           416:  * as long as the file system is mounted.
        !           417:  *
        !           418:  * only the vm code calls this.
        !           419:  */
        !           420: getfsx(dev)
        !           421:        dev_t dev;
        !           422: {
        !           423:        register struct mount *mp;
        !           424: 
        !           425:        if (dev == swapdev)
        !           426:                return (MSWAPX);
        !           427:        mp = findmount(0, dev);
        !           428:        if (mp == NULL)
        !           429:                return (-1);
        !           430:        return (mp - &mount[0]);
        !           431: }
        !           432: 
        !           433: /*
        !           434:  * Update is the internal name of 'sync'.  It goes through the disk
        !           435:  * queues to initiate sandbagged IO; goes through the inodes to write
        !           436:  * modified nodes; and it goes through the mount table to initiate modified
        !           437:  * super blocks.
        !           438:  */
        !           439: update()
        !           440: {
        !           441:        register struct inode *ip;
        !           442: 
        !           443:        if (updlock)
        !           444:                return;
        !           445:        updlock++;
        !           446:        /*
        !           447:         * Write back each (modified) inode.
        !           448:         */
        !           449:        for (ip = inode; ip < inodeNINODE; ip++)
        !           450:                if((ip->i_flag&ILOCK)==0 && ip->i_count) {
        !           451:                        ip->i_flag |= ILOCK;
        !           452:                        ip->i_count++;
        !           453:                        iupdat(ip, &time, &time, 0);
        !           454:                        iput(ip);
        !           455:                }
        !           456:        updlock = 0;
        !           457:        /*
        !           458:         * Force stale buffer cache information to be flushed,
        !           459:         * for all devices.
        !           460:         */
        !           461:        trace(TR_BFIN, updlock, 0);
        !           462:        bflush(NODEV);
        !           463:        trace(TR_BFOUT, updlock, 0);
        !           464: }

unix.superglobalmegacorp.com

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