7250: #
7251: #include "../param.h"
7252: #include "../systm.h"
7253: #include "../user.h"
7254: #include "../inode.h"
7255: #include "../filsys.h"
7256: #include "../conf.h"
7257: #include "../buf.h"
7258: 
7259: /*
7260:  * Look up an inode by device,inumber.
7261:  * If it is in core (in the inode structure),
7262:  * honor the locking protocol.
7263:  * If it is not in core, read it in from the
7264:  * specified device.
7265:  * If the inode is mounted on, perform
7266:  * the indicated indirection.
7267:  * In all cases, a pointer to a locked
7268:  * inode structure is returned.
7269:  *
7270:  * printf warning: no inodes -- if the inode
7271:  *      structure is full
7272:  * panic: no imt -- if the mounted file
7273:  *      system is not in the mount table.
7274:  *      "cannot happen"
7275:  */
7276: iget(dev, ino)
7277: {
7278:         register struct inode *p;
7279:         register *ip2;
7280:         int *ip1;
7281:         register struct mount *ip;
7282: 
7283: loop:
7284:         ip = NULL;
7285:         for(p = &inode[0]; p < &inode[NINODE]; p++) {
7286:                 if(dev==p->i_dev && ino==p->i_number) {
7287:                         if((p->i_flag&ILOCK) != 0) {
7288:                                 p->i_flag =| IWANT;
7289:                                 sleep(p, PINOD);
7290:                                 goto loop;
7291:                         }
7292:                         if((p->i_flag&IMOUNT) != 0) {
7293: 
7294:                                 for(ip = &mount[0]; ip < &mount[NMOUNT]; ip++)
7295:                                 if(ip->m_inodp == p) {
7296:                                         dev = ip->m_dev;
7297:                                         ino = ROOTINO;
7298:                                         goto loop;
7299:                                 }
7300:                                 panic("no imt");
7301:                         }
7302:                         p->i_count++;
7303:                         p->i_flag =| ILOCK;
7304:                         return(p);
7305:                 }
7306:                 if(ip==NULL && p->i_count==0)
7307:                         ip = p;
7308:         }
7309:         if((p=ip) == NULL) {
7310:                 printf("Inode table overflow\n");
7311:                 u.u_error = ENFILE;
7312:                 return(NULL);
7313:         }
7314:         p->i_dev = dev;
7315:         p->i_number = ino;
7316:         p->i_flag = ILOCK;
7317:         p->i_count++;
7318:         p->i_lastr = -1;
7319:         ip = bread(dev, ldiv(ino+31,16));
7320:         /*
7321:          * Check I/O errors
7322:          */
7323:         if (ip->b_flags&B_ERROR) {
7324:                 brelse(ip);
7325:                 iput(p);
7326:                 return(NULL);
7327:         }
7328:         ip1 = ip->b_addr + 32*lrem(ino+31, 16);
7329:         ip2 = &p->i_mode;
7330:         while(ip2 < &p->i_addr[8])
7331:                 *ip2++ = *ip1++;
7332:         brelse(ip);
7333:         return(p);
7334: }
7335: /* ---------------------------       */
7336: 
7337: /*
7338:  * Decrement reference count of
7339:  * an inode structure.
7340:  * On the last reference,
7341:  * write the inode out and if necessary,
7342:  * truncate and deallocate the file.
7343:  */
7344: iput(p)
7345: struct inode *p;
7346: {
7347:         register *rp;
7348: 
7349:         rp = p;
7350:         if(rp->i_count == 1) {
7351:                 rp->i_flag =| ILOCK;
7352:                 if(rp->i_nlink <= 0) {
7353:                         itrunc(rp);
7354:                         rp->i_mode = 0;
7355:                         ifree(rp->i_dev, rp->i_number);
7356:                 }
7357:                 iupdat(rp, time);
7358:                 prele(rp);
7359:                 rp->i_flag = 0;
7360:                 rp->i_number = 0;
7361:         }
7362:         rp->i_count--;
7363:         prele(rp);
7364: }
7365: /* ---------------------------       */
7366: 
7367: /*
7368:  * Check accessed and update flags on
7369:  * an inode structure.
7370:  * If either is on, update the inode
7371:  * with the corresponding dates
7372:  * set to the argument tm.
7373:  */
7374: iupdat(p, tm)
7375: int *p;
7376: int *tm;
7377: {
7378:         register *ip1, *ip2, *rp;
7379:         int *bp, i;
7380: 
7381:         rp = p;
7382:         if((rp->i_flag&(IUPD|IACC)) != 0) {
7383:                 if(getfs(rp->i_dev)->s_ronly)
7384:                         return;
7385:                 i = rp->i_number+31;
7386:                 bp = bread(rp->i_dev, ldiv(i,16));
7387:                 ip1 = bp->b_addr + 32*lrem(i, 16);
7388:                 ip2 = &rp->i_mode;
7389:                 while(ip2 < &rp->i_addr[8])
7390:                         *ip1++ = *ip2++;
7391:                 if(rp->i_flag&IACC) {
7392:                         *ip1++ = time[0];
7393:                         *ip1++ = time[1];
7394:                 } else
7395:                         ip1 =+ 2;
7396:                 if(rp->i_flag&IUPD) {
7397:                         *ip1++ = *tm++;
7398:                         *ip1++ = *tm;
7399:                 }
7400:                 bwrite(bp);
7401:         }
7402: }
7403: /* ---------------------------       */
7404: 
7405: /*
7406:  * Free all the disk blocks associated
7407:  * with the specified inode structure.
7408:  * The blocks of the file are removed
7409:  * in reverse order. This FILO
7410:  * algorithm will tend to maintain
7411:  * a contiguous free list much longer
7412:  * than FIFO.
7413:  */
7414: itrunc(ip)
7415: int *ip;
7416: {
7417:         register *rp, *bp, *cp;
7418:         int *dp, *ep;
7419: 
7420:         rp = ip;
7421:         if((rp->i_mode&(IFCHR&IFBLK)) != 0)
7422:                 return;
7423:         for(ip = &rp->i_addr[7]; ip >= &rp->i_addr[0]; ip--)
7424:         if(*ip) {
7425:                 if((rp->i_mode&ILARG) != 0) {
7426:                         bp = bread(rp->i_dev, *ip);
7427: 
7428:                         for(cp = bp->b_addr+512; cp >= bp->b_addr; cp--)
7429:                         if(*cp) {
7430:                                 if(ip == &rp->i_addr[7]) {
7431:                                         dp = bread(rp->i_dev, *cp);
7432: 
7433:                                         for(ep = dp->b_addr+512; ep >= dp->b_addr; ep--)
7434:                                         if(*ep)
7435:                                                 free(rp->i_dev, *ep);
7436:                                         brelse(dp);
7437:                                 }
7438:                                 free(rp->i_dev, *cp);
7439:                         }
7440:                         brelse(bp);
7441:                 }
7442:                 free(rp->i_dev, *ip);
7443:                 *ip = 0;
7444:         }
7445:         rp->i_mode =& ~ILARG;
7446:         rp->i_size0 = 0;
7447:         rp->i_size1 = 0;
7448:         rp->i_flag =| IUPD;
7449: }
7450: /* ---------------------------       */
7451: 
7452: /*
7453:  * Make a new file.
7454:  */
7455: maknode(mode)
7456: {
7457:         register *ip;
7458: 
7459:         ip = ialloc(u.u_pdir->i_dev);
7460:         if (ip==NULL)
7461:                 return(NULL);
7462:         ip->i_flag =| IACC|IUPD;
7463:         ip->i_mode = mode|IALLOC;
7464:         ip->i_nlink = 1;
7465:         ip->i_uid = u.u_uid;
7466:         ip->i_gid = u.u_gid;
7467:         wdir(ip);
7468:         return(ip);
7469: }
7470: /* ---------------------------       */
7471: 
7472: /*
7473:  * Write a directory entry with
7474:  * parameters left as side effects
7475:  * to a call to namei.
7476:  */
7477: wdir(ip)
7478: int *ip;
7479: {
7480:         register char *cp1, *cp2;
7481: 
7482:         u.u_dent.u_ino = ip->i_number;
7483:         cp1 = &u.u_dent.u_name[0];
7484:         for(cp2 = &u.u_dbuf[0]; cp2 < &u.u_dbuf[DIRSIZ];)
7485:                 *cp1++ = *cp2++;
7486:         u.u_count = DIRSIZ+2;
7487:         u.u_segflg = 1;
7488:         u.u_base = &u.u_dent;
7489:         writei(u.u_pdir);
7490:         iput(u.u_pdir);
7491: }
7492: /* ---------------------------       */