Annotation of 43BSDReno/sbin/fsck/inode.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980, 1986 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted provided
                      6:  * that: (1) source distributions retain this entire copyright notice and
                      7:  * comment, and (2) distributions including binaries display the following
                      8:  * acknowledgement:  ``This product includes software developed by the
                      9:  * University of California, Berkeley and its contributors'' in the
                     10:  * documentation or other materials provided with the distribution and in
                     11:  * all advertising materials mentioning features or use of this software.
                     12:  * Neither the name of the University nor the names of its contributors may
                     13:  * be used to endorse or promote products derived from this software without
                     14:  * specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     16:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     17:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: static char sccsid[] = "@(#)inode.c    5.17 (Berkeley) 7/27/90";
                     22: #endif /* not lint */
                     23: 
                     24: #include <sys/param.h>
                     25: #include <ufs/dinode.h>
                     26: #include <ufs/fs.h>
                     27: #include <ufs/dir.h>
                     28: #include <pwd.h>
                     29: #include <stdlib.h>
                     30: #include <string.h>
                     31: #include "fsck.h"
                     32: 
                     33: static ino_t startinum;
                     34: 
                     35: ckinode(dp, idesc)
                     36:        struct dinode *dp;
                     37:        register struct inodesc *idesc;
                     38: {
                     39:        register daddr_t *ap;
                     40:        long ret, n, ndb, offset;
                     41:        struct dinode dino;
                     42: 
                     43:        if (idesc->id_fix != IGNORE)
                     44:                idesc->id_fix = DONTKNOW;
                     45:        idesc->id_entryno = 0;
                     46:        idesc->id_filesize = dp->di_size;
                     47:        if ((dp->di_mode & IFMT) == IFBLK || (dp->di_mode & IFMT) == IFCHR)
                     48:                return (KEEPON);
                     49:        dino = *dp;
                     50:        ndb = howmany(dino.di_size, sblock.fs_bsize);
                     51:        for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) {
                     52:                if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0)
                     53:                        idesc->id_numfrags =
                     54:                                numfrags(&sblock, fragroundup(&sblock, offset));
                     55:                else
                     56:                        idesc->id_numfrags = sblock.fs_frag;
                     57:                if (*ap == 0)
                     58:                        continue;
                     59:                idesc->id_blkno = *ap;
                     60:                if (idesc->id_type == ADDR)
                     61:                        ret = (*idesc->id_func)(idesc);
                     62:                else
                     63:                        ret = dirscan(idesc);
                     64:                if (ret & STOP)
                     65:                        return (ret);
                     66:        }
                     67:        idesc->id_numfrags = sblock.fs_frag;
                     68:        for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
                     69:                if (*ap) {
                     70:                        idesc->id_blkno = *ap;
                     71:                        ret = iblock(idesc, n,
                     72:                                dino.di_size - sblock.fs_bsize * NDADDR);
                     73:                        if (ret & STOP)
                     74:                                return (ret);
                     75:                }
                     76:        }
                     77:        return (KEEPON);
                     78: }
                     79: 
                     80: iblock(idesc, ilevel, isize)
                     81:        struct inodesc *idesc;
                     82:        register long ilevel;
                     83:        u_long isize;
                     84: {
                     85:        register daddr_t *ap;
                     86:        register daddr_t *aplim;
                     87:        int i, n, (*func)(), nif, sizepb;
                     88:        register struct bufarea *bp;
                     89:        char buf[BUFSIZ];
                     90:        extern int dirscan(), pass1check();
                     91: 
                     92:        if (idesc->id_type == ADDR) {
                     93:                func = idesc->id_func;
                     94:                if (((n = (*func)(idesc)) & KEEPON) == 0)
                     95:                        return (n);
                     96:        } else
                     97:                func = dirscan;
                     98:        if (chkrange(idesc->id_blkno, idesc->id_numfrags))
                     99:                return (SKIP);
                    100:        bp = getdatablk(idesc->id_blkno, sblock.fs_bsize);
                    101:        ilevel--;
                    102:        for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
                    103:                sizepb *= NINDIR(&sblock);
                    104:        nif = isize / sizepb + 1;
                    105:        if (nif > NINDIR(&sblock))
                    106:                nif = NINDIR(&sblock);
                    107:        if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
                    108:                aplim = &bp->b_un.b_indir[NINDIR(&sblock)];
                    109:                for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) {
                    110:                        if (*ap == 0)
                    111:                                continue;
                    112:                        (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%lu",
                    113:                                idesc->id_number);
                    114:                        if (dofix(idesc, buf)) {
                    115:                                *ap = 0;
                    116:                                dirty(bp);
                    117:                        }
                    118:                }
                    119:                flush(fswritefd, bp);
                    120:        }
                    121:        aplim = &bp->b_un.b_indir[nif];
                    122:        for (ap = bp->b_un.b_indir, i = 1; ap < aplim; ap++, i++) {
                    123:                if (*ap) {
                    124:                        idesc->id_blkno = *ap;
                    125:                        if (ilevel > 0)
                    126:                                n = iblock(idesc, ilevel, isize - i * sizepb);
                    127:                        else
                    128:                                n = (*func)(idesc);
                    129:                        if (n & STOP) {
                    130:                                bp->b_flags &= ~B_INUSE;
                    131:                                return (n);
                    132:                        }
                    133:                }
                    134:        }
                    135:        bp->b_flags &= ~B_INUSE;
                    136:        return (KEEPON);
                    137: }
                    138: 
                    139: /*
                    140:  * Check that a block in a legal block number.
                    141:  * Return 0 if in range, 1 if out of range.
                    142:  */
                    143: chkrange(blk, cnt)
                    144:        daddr_t blk;
                    145:        int cnt;
                    146: {
                    147:        register int c;
                    148: 
                    149:        if ((unsigned)(blk + cnt) > maxfsblock)
                    150:                return (1);
                    151:        c = dtog(&sblock, blk);
                    152:        if (blk < cgdmin(&sblock, c)) {
                    153:                if ((blk + cnt) > cgsblock(&sblock, c)) {
                    154:                        if (debug) {
                    155:                                printf("blk %ld < cgdmin %ld;",
                    156:                                    blk, cgdmin(&sblock, c));
                    157:                                printf(" blk + cnt %ld > cgsbase %ld\n",
                    158:                                    blk + cnt, cgsblock(&sblock, c));
                    159:                        }
                    160:                        return (1);
                    161:                }
                    162:        } else {
                    163:                if ((blk + cnt) > cgbase(&sblock, c+1)) {
                    164:                        if (debug)  {
                    165:                                printf("blk %ld >= cgdmin %ld;",
                    166:                                    blk, cgdmin(&sblock, c));
                    167:                                printf(" blk + cnt %ld > sblock.fs_fpg %ld\n",
                    168:                                    blk+cnt, sblock.fs_fpg);
                    169:                        }
                    170:                        return (1);
                    171:                }
                    172:        }
                    173:        return (0);
                    174: }
                    175: 
                    176: /*
                    177:  * General purpose interface for reading inodes.
                    178:  */
                    179: struct dinode *
                    180: ginode(inumber)
                    181:        ino_t inumber;
                    182: {
                    183:        daddr_t iblk;
                    184: 
                    185:        if (inumber < ROOTINO || inumber > maxino)
                    186:                errexit("bad inode number %d to ginode\n", inumber);
                    187:        if (startinum == 0 ||
                    188:            inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
                    189:                iblk = itod(&sblock, inumber);
                    190:                if (pbp != 0)
                    191:                        pbp->b_flags &= ~B_INUSE;
                    192:                pbp = getdatablk(iblk, sblock.fs_bsize);
                    193:                startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
                    194:        }
                    195:        return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]);
                    196: }
                    197: 
                    198: /*
                    199:  * Special purpose version of ginode used to optimize first pass
                    200:  * over all the inodes in numerical order.
                    201:  */
                    202: ino_t nextino, lastinum;
                    203: long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
                    204: struct dinode *inodebuf;
                    205: 
                    206: struct dinode *
                    207: getnextinode(inumber)
                    208:        ino_t inumber;
                    209: {
                    210:        long size;
                    211:        daddr_t dblk;
                    212:        static struct dinode *dp;
                    213: 
                    214:        if (inumber != nextino++ || inumber > maxino)
                    215:                errexit("bad inode number %d to nextinode\n", inumber);
                    216:        if (inumber >= lastinum) {
                    217:                readcnt++;
                    218:                dblk = fsbtodb(&sblock, itod(&sblock, lastinum));
                    219:                if (readcnt % readpercg == 0) {
                    220:                        size = partialsize;
                    221:                        lastinum += partialcnt;
                    222:                } else {
                    223:                        size = inobufsize;
                    224:                        lastinum += fullcnt;
                    225:                }
                    226:                (void)bread(fsreadfd, (char *)inodebuf, dblk, size); /* ??? */
                    227:                dp = inodebuf;
                    228:        }
                    229:        return (dp++);
                    230: }
                    231: 
                    232: resetinodebuf()
                    233: {
                    234: 
                    235:        startinum = 0;
                    236:        nextino = 0;
                    237:        lastinum = 0;
                    238:        readcnt = 0;
                    239:        inobufsize = blkroundup(&sblock, INOBUFSIZE);
                    240:        fullcnt = inobufsize / sizeof(struct dinode);
                    241:        readpercg = sblock.fs_ipg / fullcnt;
                    242:        partialcnt = sblock.fs_ipg % fullcnt;
                    243:        partialsize = partialcnt * sizeof(struct dinode);
                    244:        if (partialcnt != 0) {
                    245:                readpercg++;
                    246:        } else {
                    247:                partialcnt = fullcnt;
                    248:                partialsize = inobufsize;
                    249:        }
                    250:        if (inodebuf == NULL &&
                    251:            (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL)
                    252:                errexit("Cannot allocate space for inode buffer\n");
                    253:        while (nextino < ROOTINO)
                    254:                (void)getnextinode(nextino);
                    255: }
                    256: 
                    257: freeinodebuf()
                    258: {
                    259: 
                    260:        if (inodebuf != NULL)
                    261:                free((char *)inodebuf);
                    262:        inodebuf = NULL;
                    263: }
                    264: 
                    265: /*
                    266:  * Routines to maintain information about directory inodes.
                    267:  * This is built during the first pass and used during the
                    268:  * second and third passes.
                    269:  *
                    270:  * Enter inodes into the cache.
                    271:  */
                    272: cacheino(dp, inumber)
                    273:        register struct dinode *dp;
                    274:        ino_t inumber;
                    275: {
                    276:        register struct inoinfo *inp;
                    277:        struct inoinfo **inpp;
                    278:        unsigned int blks;
                    279: 
                    280:        blks = howmany(dp->di_size, sblock.fs_bsize);
                    281:        if (blks > NDADDR)
                    282:                blks = NDADDR + NIADDR;
                    283:        inp = (struct inoinfo *)
                    284:                malloc(sizeof(*inp) + (blks - 1) * sizeof(daddr_t));
                    285:        if (inp == NULL)
                    286:                return;
                    287:        inpp = &inphead[inumber % numdirs];
                    288:        inp->i_nexthash = *inpp;
                    289:        *inpp = inp;
                    290:        inp->i_parent = (ino_t)0;
                    291:        inp->i_dotdot = (ino_t)0;
                    292:        inp->i_number = inumber;
                    293:        inp->i_isize = dp->di_size;
                    294:        inp->i_numblks = blks * sizeof(daddr_t);
                    295:        bcopy((char *)&dp->di_db[0], (char *)&inp->i_blks[0],
                    296:            (size_t)inp->i_numblks);
                    297:        if (inplast == listmax) {
                    298:                listmax += 100;
                    299:                inpsort = (struct inoinfo **)realloc((char *)inpsort,
                    300:                    (unsigned)listmax * sizeof(struct inoinfo *));
                    301:                if (inpsort == NULL)
                    302:                        errexit("cannot increase directory list");
                    303:        }
                    304:        inpsort[inplast++] = inp;
                    305: }
                    306: 
                    307: /*
                    308:  * Look up an inode cache structure.
                    309:  */
                    310: struct inoinfo *
                    311: getinoinfo(inumber)
                    312:        ino_t inumber;
                    313: {
                    314:        register struct inoinfo *inp;
                    315: 
                    316:        for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) {
                    317:                if (inp->i_number != inumber)
                    318:                        continue;
                    319:                return (inp);
                    320:        }
                    321:        errexit("cannot find inode %d\n", inumber);
                    322:        return ((struct inoinfo *)0);
                    323: }
                    324: 
                    325: /*
                    326:  * Clean up all the inode cache structure.
                    327:  */
                    328: inocleanup()
                    329: {
                    330:        register struct inoinfo **inpp;
                    331: 
                    332:        if (inphead == NULL)
                    333:                return;
                    334:        for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--)
                    335:                free((char *)(*inpp));
                    336:        free((char *)inphead);
                    337:        free((char *)inpsort);
                    338:        inphead = inpsort = NULL;
                    339: }
                    340:        
                    341: inodirty()
                    342: {
                    343:        
                    344:        dirty(pbp);
                    345: }
                    346: 
                    347: clri(idesc, type, flag)
                    348:        register struct inodesc *idesc;
                    349:        char *type;
                    350:        int flag;
                    351: {
                    352:        register struct dinode *dp;
                    353: 
                    354:        dp = ginode(idesc->id_number);
                    355:        if (flag == 1) {
                    356:                pwarn("%s %s", type,
                    357:                    (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE");
                    358:                pinode(idesc->id_number);
                    359:        }
                    360:        if (preen || reply("CLEAR") == 1) {
                    361:                if (preen)
                    362:                        printf(" (CLEARED)\n");
                    363:                n_files--;
                    364:                (void)ckinode(dp, idesc);
                    365:                clearinode(dp);
                    366:                statemap[idesc->id_number] = USTATE;
                    367:                inodirty();
                    368:        }
                    369: }
                    370: 
                    371: findname(idesc)
                    372:        struct inodesc *idesc;
                    373: {
                    374:        register struct direct *dirp = idesc->id_dirp;
                    375: 
                    376:        if (dirp->d_ino != idesc->id_parent)
                    377:                return (KEEPON);
                    378:        bcopy(dirp->d_name, idesc->id_name, (size_t)dirp->d_namlen + 1);
                    379:        return (STOP|FOUND);
                    380: }
                    381: 
                    382: findino(idesc)
                    383:        struct inodesc *idesc;
                    384: {
                    385:        register struct direct *dirp = idesc->id_dirp;
                    386: 
                    387:        if (dirp->d_ino == 0)
                    388:                return (KEEPON);
                    389:        if (strcmp(dirp->d_name, idesc->id_name) == 0 &&
                    390:            dirp->d_ino >= ROOTINO && dirp->d_ino <= maxino) {
                    391:                idesc->id_parent = dirp->d_ino;
                    392:                return (STOP|FOUND);
                    393:        }
                    394:        return (KEEPON);
                    395: }
                    396: 
                    397: pinode(ino)
                    398:        ino_t ino;
                    399: {
                    400:        register struct dinode *dp;
                    401:        register char *p;
                    402:        struct passwd *pw;
                    403:        char *ctime();
                    404: 
                    405:        printf(" I=%lu ", ino);
                    406:        if (ino < ROOTINO || ino > maxino)
                    407:                return;
                    408:        dp = ginode(ino);
                    409:        printf(" OWNER=");
                    410:        if ((pw = getpwuid((int)dp->di_uid)) != 0)
                    411:                printf("%s ", pw->pw_name);
                    412:        else
                    413:                printf("%u ", (unsigned)dp->di_uid);
                    414:        printf("MODE=%o\n", dp->di_mode);
                    415:        if (preen)
                    416:                printf("%s: ", devname);
                    417:        printf("SIZE=%lu ", dp->di_size);
                    418:        p = ctime(&dp->di_mtime);
                    419:        printf("MTIME=%12.12s %4.4s ", p + 4, p + 20);
                    420: }
                    421: 
                    422: blkerror(ino, type, blk)
                    423:        ino_t ino;
                    424:        char *type;
                    425:        daddr_t blk;
                    426: {
                    427: 
                    428:        pfatal("%ld %s I=%lu", blk, type, ino);
                    429:        printf("\n");
                    430:        switch (statemap[ino]) {
                    431: 
                    432:        case FSTATE:
                    433:                statemap[ino] = FCLEAR;
                    434:                return;
                    435: 
                    436:        case DSTATE:
                    437:                statemap[ino] = DCLEAR;
                    438:                return;
                    439: 
                    440:        case FCLEAR:
                    441:        case DCLEAR:
                    442:                return;
                    443: 
                    444:        default:
                    445:                errexit("BAD STATE %d TO BLKERR", statemap[ino]);
                    446:                /* NOTREACHED */
                    447:        }
                    448: }
                    449: 
                    450: /*
                    451:  * allocate an unused inode
                    452:  */
                    453: ino_t
                    454: allocino(request, type)
                    455:        ino_t request;
                    456:        int type;
                    457: {
                    458:        register ino_t ino;
                    459:        register struct dinode *dp;
                    460: 
                    461:        if (request == 0)
                    462:                request = ROOTINO;
                    463:        else if (statemap[request] != USTATE)
                    464:                return (0);
                    465:        for (ino = request; ino < maxino; ino++)
                    466:                if (statemap[ino] == USTATE)
                    467:                        break;
                    468:        if (ino == maxino)
                    469:                return (0);
                    470:        switch (type & IFMT) {
                    471:        case IFDIR:
                    472:                statemap[ino] = DSTATE;
                    473:                break;
                    474:        case IFREG:
                    475:        case IFLNK:
                    476:                statemap[ino] = FSTATE;
                    477:                break;
                    478:        default:
                    479:                return (0);
                    480:        }
                    481:        dp = ginode(ino);
                    482:        dp->di_db[0] = allocblk((long)1);
                    483:        if (dp->di_db[0] == 0) {
                    484:                statemap[ino] = USTATE;
                    485:                return (0);
                    486:        }
                    487:        dp->di_mode = type;
                    488:        (void)time(&dp->di_atime);
                    489:        dp->di_mtime = dp->di_ctime = dp->di_atime;
                    490:        dp->di_size = sblock.fs_fsize;
                    491:        dp->di_blocks = btodb(sblock.fs_fsize);
                    492:        n_files++;
                    493:        inodirty();
                    494:        return (ino);
                    495: }
                    496: 
                    497: /*
                    498:  * deallocate an inode
                    499:  */
                    500: freeino(ino)
                    501:        ino_t ino;
                    502: {
                    503:        struct inodesc idesc;
                    504:        extern int pass4check();
                    505:        struct dinode *dp;
                    506: 
                    507:        bzero((char *)&idesc, sizeof(struct inodesc));
                    508:        idesc.id_type = ADDR;
                    509:        idesc.id_func = pass4check;
                    510:        idesc.id_number = ino;
                    511:        dp = ginode(ino);
                    512:        (void)ckinode(dp, &idesc);
                    513:        clearinode(dp);
                    514:        inodirty();
                    515:        statemap[ino] = USTATE;
                    516:        n_files--;
                    517: }

unix.superglobalmegacorp.com

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