Annotation of researchv10no/sys/os/iget.c, revision 1.1.1.1

1.1       root        1: #include "sys/param.h"
                      2: #include "sys/user.h"
                      3: #include "sys/inode.h"
                      4: #include "sys/conf.h"
                      5: 
                      6: #define        INOHSZ  63
                      7: /* INOHASH can't depend on fstype as long as unmount changes fstyp to err-fs */
                      8: #define        INOHASH(dev, ino)       (((dev)+(ino))%INOHSZ)
                      9: struct inode *inohash[INOHSZ];
                     10: struct inode *ifreel;
                     11: 
                     12: /*
                     13:  * Initialize hash links for inodes
                     14:  * and build inode free list.
                     15:  */
                     16: ihinit()
                     17: {
                     18:        register int i;
                     19:        register struct inode *ip = inode;
                     20: 
                     21:        ifreel = inode;
                     22:        for (i = 0; i < inodecnt-1; i++, ip++)
                     23:                ip->i_hlink = ip + 1;
                     24:        ip->i_hlink = NULL;
                     25:        for (i = 0; i < INOHSZ; i++)
                     26:                inohash[i] = NULL;
                     27: }
                     28: 
                     29: /*
                     30:  * Find an inode if it is incore.
                     31:  */
                     32: struct inode *
                     33: ifind(hp, ino)
                     34: register struct inode *hp;
                     35: register ino_t ino;
                     36: {
                     37:        register struct inode *ip;
                     38: 
                     39:        for (ip = inohash[INOHASH(hp->i_dev,ino)]; ip; ip = ip->i_hlink)
                     40:                if (ino==ip->i_number && hp->i_dev==ip->i_dev && hp->i_fstyp==ip->i_fstyp)
                     41:                        return (ip);
                     42:        return ((struct inode *)0);
                     43: }
                     44: 
                     45: /*
                     46:  * see if there are any inodes save the given one
                     47:  * in the same filesystem
                     48:  * used by unmount routines to decide whether fs is busy
                     49:  * try to unmount anything mounted atop this fs
                     50:  * -- botch: deeply nested filesystems may run the system
                     51:  * out of stack and cause a crash
                     52:  */
                     53: 
                     54: int
                     55: ifsbusy(rip)
                     56: register struct inode *rip;
                     57: {
                     58:        register struct inode *ip;
                     59: 
                     60:        for (ip = inode; ip < inodeNINODE; ip++) {
                     61:                if (ip->i_count == 0)
                     62:                        continue;
                     63:                if (ip->i_mpoint != rip->i_mpoint)
                     64:                        continue;
                     65:                if (ip->i_mroot) {      /* something mounted here? */
                     66:                        ip->i_count++;
                     67:                        (*fstypsw[ip->i_mroot->i_fstyp]->t_mount)((struct inode *)NULL,
                     68:                                ip, 0, 0, ip->i_mroot->i_fstyp);
                     69:                        if (ip->i_count == 1) { /* just our reference left? */
                     70:                                idec(ip);
                     71:                                continue;
                     72:                        }
                     73:                        idec(ip);
                     74:                }
                     75:                if (ip != rip)
                     76:                        return (1);
                     77:        }
                     78:        return (0);
                     79: }
                     80: 
                     81: /*
                     82:  * mark inaccessible all i-nodes in this filesystem
                     83:  * used for forced unmounting
                     84:  * any further IO through those inodes will produce an error
                     85:  * -- it's annoying that ERRFS must be manifest
                     86:  */
                     87: 
                     88: #define        ERRFS   5
                     89: ifsinacc(rip)
                     90: register struct inode *rip;
                     91: {
                     92:        register struct inode *ip;
                     93: 
                     94:        rip = rip->i_mpoint;
                     95:        for (ip = inode; ip < inodeNINODE; ip++) {
                     96:                if (ip->i_count == 0)
                     97:                        continue;
                     98:                if (ip->i_mpoint != rip)
                     99:                        continue;
                    100:                ip->i_fstyp = ERRFS;    /* yes, always */
                    101:                ip->i_mpoint = rootdir;         /* hmm */
                    102:                if (ip->i_mroot)
                    103:                        (*fstypsw[ip->i_mroot->i_fstyp]->t_mount)((struct inode *)NULL,
                    104:                                ip, 0, 0, ip->i_mroot->i_fstyp);
                    105:        }
                    106: }
                    107: 
                    108: #ifndef plock          /* done inline */
                    109: /*
                    110:  * Lock an inode
                    111:  * If its already locked,
                    112:  * set the WANT bit and sleep.
                    113:  */
                    114: plock(ip)
                    115: register struct inode *ip;
                    116: {
                    117: 
                    118:        while(ip->i_flag&ILOCK) {
                    119:                ip->i_flag |= IWANT;
                    120:                sleep((caddr_t)ip, PINOD);
                    121:        }
                    122:        ip->i_flag |= ILOCK;
                    123: }
                    124: 
                    125: /*
                    126:  * Unlock an inode.
                    127:  * If WANT bit is on,
                    128:  * wakeup.
                    129:  */
                    130: prele(ip)
                    131: register struct inode *ip;
                    132: {
                    133:        ip->i_flag &= ~ILOCK;
                    134:        if(ip->i_flag&IWANT) {
                    135:                ip->i_flag &= ~IWANT;
                    136:                wakeup((caddr_t)ip);
                    137:        }
                    138: }
                    139: #endif
                    140: 
                    141: 
                    142: /*
                    143:  * Look up an inode by filsys, i-number.
                    144:  * filsys is denoted by some inode in that filesystem.
                    145:  * If the inode is mounted on, perform
                    146:  * the indicated indirection.
                    147:  * If it is in core (in the inode structure),
                    148:  * honor the locking protocol.
                    149:  * If it is not in core, fill in the fields that
                    150:  * signify the inode`s `name' (number, dev, filsys, fstyp)
                    151:  * and leave the rest blank, to be filled in by the caller.
                    152:  * A `blank' inode has i_count == 1.
                    153:  * In all cases, a pointer to a locked
                    154:  * inode structure is returned.
                    155:  */
                    156: struct inode *
                    157: iget(fip, dev, ino)
                    158: register struct inode *fip;
                    159: dev_t dev;
                    160: register ino_t ino;
                    161: {
                    162:        register struct inode *ip;
                    163:        register int slot;
                    164: 
                    165: loop:
                    166:        slot = INOHASH(dev, ino);
                    167:        for (ip = inohash[slot]; ip; ip = ip->i_hlink) {
                    168:                if(ino == ip->i_number && dev == ip->i_dev
                    169:                        && fip->i_fstyp == ip->i_fstyp) {
                    170: mloop:
                    171:                        if((ip->i_flag&ILOCK) != 0) {
                    172:                                ip->i_flag |= IWANT;
                    173:                                sleep((caddr_t)ip, PINOD);
                    174:                                goto loop;
                    175:                        }
                    176:                        if(ip->i_mroot != NULL) {
                    177:                                ip = ip->i_mroot;
                    178:                                goto mloop;
                    179:                        }
                    180:                        ip->i_count++;
                    181:                        ip->i_flag |= ILOCK;
                    182:                        return(ip);
                    183:                }
                    184:        }
                    185:        if(ifreel == NULL) {
                    186:                tablefull("inode");
                    187:                u.u_error = ENFILE;
                    188:                return(NULL);
                    189:        }
                    190:        ip = ifreel;
                    191:        ifreel = ip->i_hlink;
                    192:        ip->i_hlink = inohash[slot];
                    193:        inohash[slot] = ip;
                    194:        ip->i_dev = dev;
                    195:        ip->i_fstyp = fip->i_fstyp;
                    196:        ip->i_number = ino;
                    197:        ip->i_flag = ILOCK;
                    198:        ip->i_count = 1;
                    199:        ip->i_sptr = NULL;
                    200:        ip->i_mroot = NULL;
                    201:        ip->i_mpoint = fip->i_mpoint;
                    202:        return (ip);
                    203: }
                    204: 
                    205: /*
                    206:  * Decrement reference count of
                    207:  * an inode structure.
                    208:  * On the last reference,
                    209:  * call closei to close the file.
                    210:  * Don't unlock unless we were the only reference.
                    211:  */
                    212: idec(ip)
                    213: register struct inode *ip;
                    214: {
                    215:        register int i;
                    216:        register struct inode *jp;
                    217: 
                    218:        if (ip->i_count == 0)
                    219:                panic("i_count==0");
                    220:        if (ip->i_count == 1) {
                    221:                ip->i_flag |= ILOCK;
                    222:                closei(ip);
                    223:                (*fstypsw[ip->i_fstyp]->t_put)(ip);
                    224:                i = INOHASH(ip->i_dev, ip->i_number);
                    225:                if (inohash[i] == ip)
                    226:                        inohash[i] = ip->i_hlink;
                    227:                else {
                    228:                        for (jp = inohash[i]; jp; jp = jp->i_hlink)
                    229:                                if (jp->i_hlink == ip) {
                    230:                                        jp->i_hlink = ip->i_hlink;
                    231:                                        goto done;
                    232:                                }
                    233:                        panic("idec");
                    234:                }
                    235: done:
                    236:                prele(ip);
                    237:                ip->i_flag = 0;
                    238:                ip->i_number = 0;
                    239:                ip->i_hlink = ifreel;
                    240:                ifreel = ip;
                    241:        }
                    242:        ip->i_count--;
                    243: }
                    244: 
                    245: /*
                    246:  * decrement the count for a locked inode.
                    247:  * unlock.
                    248:  * perhaps this should be a macro later
                    249:  */
                    250: 
                    251: iput(ip)
                    252: register struct inode *ip;
                    253: {
                    254: #if NOTDEF
                    255:        if ((ip->i_flag & ILOCK) == 0)
                    256:                panic("iput");
                    257: #endif
                    258:        if (ip->i_count == 0)
                    259:                panic("i_count==0");
                    260:        if (ip->i_count == 1)
                    261:                idec(ip);       /* will take care of lock too */
                    262:        else {
                    263:                ip->i_count--;
                    264:                prele(ip);
                    265:        }
                    266: }
                    267: 
                    268: /*
                    269:  * Check accessed and update flags on
                    270:  * an inode structure.
                    271:  * If any is on, update the inode
                    272:  * with the current time.
                    273:  * If waitfor is given, then must insure
                    274:  * i/o order so wait for write to complete.
                    275:  */
                    276: iupdat(ip, ta, tm, waitfor)
                    277: register struct inode *ip;
                    278: time_t *ta, *tm;
                    279: int waitfor;
                    280: {
                    281: 
                    282:        if((ip->i_flag&(IUPD|IACC|ICHG)) != 0)
                    283:                (*fstypsw[ip->i_fstyp]->t_updat)(ip, ta, tm, waitfor);
                    284: }
                    285: 
                    286: /*
                    287:  * allocate an in-core-only inode with no filesystem counterpart
                    288:  * used for pipes and similar things
                    289:  * a locked inode is returned, filled in and useable,
                    290:  * but not a member of any filesystem
                    291:  */
                    292: struct inode *
                    293: iuniq(fstyp)
                    294:        int fstyp;
                    295: {
                    296:        struct inode *ip;
                    297:        static ino_t ino=0;
                    298:        ino_t inostart;
                    299:        struct inode pi;                /* primer */
                    300: 
                    301:        pi.i_dev = NODEV;
                    302:        pi.i_fstyp = fstyp;
                    303:        pi.i_mpoint = NULL;
                    304:        for (inostart = ino++; ino != inostart; ino++) {
                    305:                if (ifind(&pi, ino))    /* already in use */
                    306:                        continue;
                    307:                if ((ip = iget(&pi, NODEV, ino)) == NULL)
                    308:                        return (NULL);  /* no inodes, or something */
                    309:                if (ip->i_count != 1) { /* already in use -- safety */
                    310:                        iput(ip);
                    311:                        continue;
                    312:                }
                    313:                ip->i_mode = IFREG | (0666 & ~u.u_cmask);
                    314:                ip->i_uid = u.u_uid;
                    315:                ip->i_gid = u.u_gid;
                    316:                ip->i_nlink = 0;
                    317:                return(ip);
                    318:        }
                    319:        tablefull("fake inode");
                    320:        u.u_error = ENFILE;
                    321:        return(NULL);
                    322: }

unix.superglobalmegacorp.com

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