sys/iget.c

08450 #include "../h/param.h" 08451 #include "../h/systm.h" 08452 #include "../h/mount.h" 08453 #include "../h/dir.h" 08454 #include "../h/user.h" 08455 #include "../h/inode.h" 08456 #include "../h/ino.h" 08457 #include "../h/filsys.h" 08458 #include "../h/conf.h" 08459 #include "../h/buf.h" 08460 08461 /* 08462 * Look up an inode by device,inumber. 08463 * If it is in core (in the inode structure), 08464 * honor the locking protocol. 08465 * If it is not in core, read it in from the 08466 * specified device. 08467 * If the inode is mounted on, perform 08468 * the indicated indirection. 08469 * In all cases, a pointer to a locked 08470 * inode structure is returned. 08471 * 08472 * printf warning: no inodes -- if the inode 08473 * structure is full 08474 * panic: no imt -- if the mounted file 08475 * system is not in the mount table. 08476 * "cannot happen" 08477 */ 08478 struct inode */ 08479 iget(dev, ino) 08480 dev_t dev; 08481 ino_t ino; 08482 { 08483 register struct inode *ip; 08484 register struct mount *mp; 08485 register struct inode *oip; 08486 register struct buf *bp; 08487 register struct dinode *dp; 08488 08489 loop: 08490 oip = NULL; 08491 for(ip = &inode[0]; ip < &inode[NINODE]; ip++) { 08492 if(ino == ip->i_number && dev == ip->i_dev) { 08493 if((ip->i_flag&ILOCK) != 0) { 08494 ip->i_flag |= IWANT; 08495 sleep((caddr_t)ip, PINOD); 08496 goto loop; 08497 } 08498 if((ip->i_flag&IMOUNT) != 0) { 08499 for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 08500 if(mp->m_inodp == ip) { 08501 dev = mp->m_dev; 08502 ino = ROOTINO; 08503 goto loop; 08504 } 08505 panic("no imt"); 08506 } 08507 ip->i_count++; 08508 ip->i_flag |= ILOCK; 08509 return(ip); 08510 } 08511 if(oip==NULL && ip->i_count==0) 08512 oip = ip; 08513 } 08514 ip = oip; 08515 if(ip == NULL) { 08516 printf("Inode table overflow\n"); 08517 u.u_error = ENFILE; 08518 return(NULL); 08519 } 08520 ip->i_dev = dev; 08521 ip->i_number = ino; 08522 ip->i_flag = ILOCK; 08523 ip->i_count++; 08524 ip->i_un.i_lastr = 0; 08525 bp = bread(dev, itod(ino)); 08526 /* 08527 * Check I/O errors 08528 */ 08529 if((bp->b_flags&B_ERROR) != 0) { 08530 brelse(bp); 08531 iput(ip); 08532 return(NULL); 08533 } 08534 dp = bp->b_un.b_dino; 08535 dp += itoo(ino); 08536 iexpand(ip, dp); 08537 brelse(bp); 08538 return(ip); 08539 } 08540 08541 iexpand(ip, dp) 08542 register struct inode *ip; 08543 register struct dinode *dp; 08544 { 08545 register char *p1; 08546 char *p2; 08547 int i; 08548 08549 ip->i_mode = dp->di_mode; 08550 ip->i_nlink = dp->di_nlink; 08551 ip->i_uid = dp->di_uid; 08552 ip->i_gid = dp->di_gid; 08553 ip->i_size = dp->di_size; 08554 p1 = (char *)ip->i_un.i_addr; 08555 p2 = (char *)dp->di_addr; 08556 for(i=0; i<NADDR; i++) { 08557 *p1++ = *p2++; 08558 *p1++ = 0; 08559 *p1++ = *p2++; 08560 *p1++ = *p2++; 08561 } 08562 } 08563 08564 /* 08565 * Decrement reference count of 08566 * an inode structure. 08567 * On the last reference, 08568 * write the inode out and if necessary, 08569 * truncate and deallocate the file. 08570 */ 08571 iput(ip) 08572 register struct inode *ip; 08573 { 08574 08575 if(ip->i_count == 1) { 08576 ip->i_flag |= ILOCK; 08577 if(ip->i_nlink <= 0) { 08578 itrunc(ip); 08579 ip->i_mode = 0; 08580 ip->i_flag |= IUPD|ICHG; 08581 ifree(ip->i_dev, ip->i_number); 08582 } 08583 iupdat(ip, &time, &time); 08584 prele(ip); 08585 ip->i_flag = 0; 08586 ip->i_number = 0; 08587 } 08588 ip->i_count--; 08589 prele(ip); 08590 } 08591 08592 /* 08593 * Check accessed and update flags on 08594 * an inode structure. 08595 * If any are on, update the inode 08596 * with the current time. 08597 */ 08598 iupdat(ip, ta, tm) 08599 register struct inode *ip; 08600 time_t *ta, *tm; 08601 { 08602 register struct buf *bp; 08603 struct dinode *dp; 08604 register char *p1; 08605 char *p2; 08606 int i; 08607 08608 if((ip->i_flag&(IUPD|IACC|ICHG)) != 0) { 08609 if(getfs(ip->i_dev)->s_ronly) 08610 return; 08611 bp = bread(ip->i_dev, itod(ip->i_number)); 08612 if (bp->b_flags & B_ERROR) { 08613 brelse(bp); 08614 return; 08615 } 08616 dp = bp->b_un.b_dino; 08617 dp += itoo(ip->i_number); 08618 dp->di_mode = ip->i_mode; 08619 dp->di_nlink = ip->i_nlink; 08620 dp->di_uid = ip->i_uid; 08621 dp->di_gid = ip->i_gid; 08622 dp->di_size = ip->i_size; 08623 p1 = (char *)dp->di_addr; 08624 p2 = (char *)ip->i_un.i_addr; 08625 for(i=0; i<NADDR; i++) { 08626 *p1++ = *p2++; 08627 if(*p2++ != 0 && (ip->i_mode&IFMT)!=IFMPC 08628 && (ip->i_mode&IFMT)!=IFMPB) 08629 printf("iaddress > 2^24\n"); 08630 *p1++ = *p2++; 08631 *p1++ = *p2++; 08632 } 08633 if(ip->i_flag&IACC) 08634 dp->di_atime = *ta; 08635 if(ip->i_flag&IUPD) 08636 dp->di_mtime = *tm; 08637 if(ip->i_flag&ICHG) 08638 dp->di_ctime = time; 08639 ip->i_flag &= ~(IUPD|IACC|ICHG); 08640 bdwrite(bp); 08641 } 08642 } 08643 08644 /* 08645 * Free all the disk blocks associated 08646 * with the specified inode structure. 08647 * The blocks of the file are removed 08648 * in reverse order. This FILO 08649 * algorithm will tend to maintain 08650 * a contiguous free list much longer 08651 * than FIFO. 08652 */ 08653 itrunc(ip) 08654 register struct inode *ip; 08655 { 08656 register i; 08657 dev_t dev; 08658 daddr_t bn; 08659 08660 i = ip->i_mode & IFMT; 08661 if (i!=IFREG && i!=IFDIR) 08662 return; 08663 dev = ip->i_dev; 08664 for(i=NADDR-1; i>=0; i--) { 08665 bn = ip->i_un.i_addr[i]; 08666 if(bn == (daddr_t)0) 08667 continue; 08668 ip->i_un.i_addr[i] = (daddr_t)0; 08669 switch(i) { 08670 08671 default: 08672 free(dev, bn); 08673 break; 08674 08675 case NADDR-3: 08676 tloop(dev, bn, 0, 0); 08677 break; 08678 08679 case NADDR-2: 08680 tloop(dev, bn, 1, 0); 08681 break; 08682 08683 case NADDR-1: 08684 tloop(dev, bn, 1, 1); 08685 } 08686 } 08687 ip->i_size = 0; 08688 ip->i_flag |= ICHG|IUPD; 08689 } 08690 08691 tloop(dev, bn, f1, f2) 08692 dev_t dev; 08693 daddr_t bn; 08694 { 08695 register i; 08696 register struct buf *bp; 08697 register daddr_t *bap; 08698 daddr_t nb; 08699 08700 bp = NULL; 08701 for(i=NINDIR-1; i>=0; i--) { 08702 if(bp == NULL) { 08703 bp = bread(dev, bn); 08704 if (bp->b_flags & B_ERROR) { 08705 brelse(bp); 08706 return; 08707 } 08708 bap = bp->b_un.b_daddr; 08709 } 08710 nb = bap[i]; 08711 if(nb == (daddr_t)0) 08712 continue; 08713 if(f1) { 08714 brelse(bp); 08715 bp = NULL; 08716 tloop(dev, nb, f2, 0); 08717 } else 08718 free(dev, nb); 08719 } 08720 if(bp != NULL) 08721 brelse(bp); 08722 free(dev, bn); 08723 } 08724 08725 /* 08726 * Make a new file. 08727 */ 08728 struct inode */ 08729 maknode(mode) 08730 { 08731 register struct inode *ip; 08732 08733 ip = ialloc(u.u_pdir->i_dev); 08734 if(ip == NULL) { 08735 iput(u.u_pdir); 08736 return(NULL); 08737 } 08738 ip->i_flag |= IACC|IUPD|ICHG; 08739 if((mode&IFMT) == 0) 08740 mode |= IFREG; 08741 ip->i_mode = mode & ~u.u_cmask; 08742 ip->i_nlink = 1; 08743 ip->i_uid = u.u_uid; 08744 ip->i_gid = u.u_gid; 08745 wdir(ip); 08746 return(ip); 08747 } 08748 08749 /* 08750 * Write a directory entry with 08751 * parameters left as side effects 08752 * to a call to namei. 08753 */ 08754 wdir(ip) 08755 struct inode *ip; 08756 { 08757 08758 if (u.u_pdir->i_nlink <= 0) { 08759 u.u_error = ENOTDIR; 08760 goto out; 08761 } 08762 u.u_dent.d_ino = ip->i_number; 08763 bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ); 08764 u.u_count = sizeof(struct direct); 08765 u.u_segflg = 1; 08766 u.u_base = (caddr_t)&u.u_dent; 08767 writei(u.u_pdir); 08768 out: 08769 iput(u.u_pdir); 08770 } 08771 08772 08773 08774 08775 08776 08777 08778 08779 08780 08781 08782 08783 08784 08785 08786 08787 08788 08789 08790 08791 08792 08793 08794 08795 08796 08797 08798 08799