Annotation of researchv9/sys.vax/sys/alloc.c, revision 1.1.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.