1*8106Sroot /* lfs_inode.c 4.24 82/09/06 */ 224Sbill 324Sbill #include "../h/param.h" 424Sbill #include "../h/systm.h" 524Sbill #include "../h/mount.h" 624Sbill #include "../h/dir.h" 724Sbill #include "../h/user.h" 824Sbill #include "../h/inode.h" 96569Smckusic #include "../h/fs.h" 1024Sbill #include "../h/conf.h" 1124Sbill #include "../h/buf.h" 1224Sbill #include "../h/inline.h" 137651Ssam #ifdef QUOTA 147504Sroot #include "../h/quota.h" 157504Sroot #endif 16*8106Sroot #include "../h/kernel.h" 1724Sbill 1824Sbill #define INOHSZ 63 197334Skre #if ((INOHSZ&(INOHSZ-1)) == 0) 207334Skre #define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1)) 217334Skre #else 2224Sbill #define INOHASH(dev,ino) (((dev)+(ino))%INOHSZ) 237334Skre #endif 2424Sbill 257334Skre union ihead { /* inode LRU cache, Chris Maltby */ 267334Skre union ihead *ih_head[2]; 277334Skre struct inode *ih_chain[2]; 287334Skre } ihead[INOHSZ]; 297334Skre 307334Skre struct inode *ifreeh, **ifreet; 317334Skre 3224Sbill /* 3324Sbill * Initialize hash links for inodes 3424Sbill * and build inode free list. 3524Sbill */ 3624Sbill ihinit() 3724Sbill { 3824Sbill register int i; 392737Swnj register struct inode *ip = inode; 407334Skre register union ihead *ih = ihead; 4124Sbill 427334Skre for (i = INOHSZ; --i >= 0; ih++) { 437334Skre ih->ih_head[0] = ih; 447334Skre ih->ih_head[1] = ih; 457334Skre } 467334Skre ifreeh = ip; 477334Skre ifreet = &ip->i_freef; 487334Skre ip->i_freeb = &ifreeh; 497334Skre ip->i_forw = ip; 507334Skre ip->i_back = ip; 517334Skre for (i = ninode; --i > 0; ) { 527334Skre ++ip; 537334Skre ip->i_forw = ip; 547334Skre ip->i_back = ip; 557334Skre *ifreet = ip; 567334Skre ip->i_freeb = ifreet; 577334Skre ifreet = &ip->i_freef; 587334Skre } 597334Skre ip->i_freef = NULL; 6024Sbill } 6124Sbill 627334Skre #ifdef notdef 6324Sbill /* 647334Skre * Find an inode if it is incore. 657334Skre * This is the equivalent, for inodes, 667334Skre * of ``incore'' in bio.c or ``pfind'' in subr.c. 677334Skre */ 687334Skre struct inode * 697334Skre ifind(dev, ino) 707334Skre dev_t dev; 717334Skre ino_t ino; 727334Skre { 737334Skre register struct inode *ip; 747334Skre register union ihead *ih; 757334Skre 767334Skre ih = &ihead[INOHASH(dev, ino)]; 777334Skre for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) 787334Skre if (ino==ip->i_number && dev==ip->i_dev) 797334Skre return (ip); 807334Skre return ((struct inode *)0); 817334Skre } 827334Skre #endif notdef 837334Skre 847334Skre /* 8524Sbill * Look up an inode by device,inumber. 8624Sbill * If it is in core (in the inode structure), 8724Sbill * honor the locking protocol. 8824Sbill * If it is not in core, read it in from the 8924Sbill * specified device. 9024Sbill * If the inode is mounted on, perform 9124Sbill * the indicated indirection. 9224Sbill * In all cases, a pointer to a locked 9324Sbill * inode structure is returned. 9424Sbill * 9524Sbill * panic: no imt -- if the mounted file 9624Sbill * system is not in the mount table. 9724Sbill * "cannot happen" 9824Sbill */ 9924Sbill struct inode * 1006569Smckusic iget(dev, fs, ino) 1014818Swnj dev_t dev; 1026569Smckusic register struct fs *fs; 1034818Swnj ino_t ino; 10424Sbill { 1057335Skre register struct inode *ip; 1067335Skre register union ihead *ih; 10724Sbill register struct mount *mp; 10824Sbill register struct buf *bp; 10924Sbill register struct dinode *dp; 1107334Skre register struct inode *iq; 11124Sbill 11224Sbill loop: 1136569Smckusic if (getfs(dev) != fs) 1146569Smckusic panic("iget: bad fs"); 1157334Skre ih = &ihead[INOHASH(dev, ino)]; 1167334Skre for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) 1174818Swnj if (ino == ip->i_number && dev == ip->i_dev) { 1184818Swnj if ((ip->i_flag&ILOCK) != 0) { 11924Sbill ip->i_flag |= IWANT; 12024Sbill sleep((caddr_t)ip, PINOD); 12124Sbill goto loop; 12224Sbill } 1234818Swnj if ((ip->i_flag&IMOUNT) != 0) { 1246569Smckusic for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 1257334Skre if(mp->m_inodp == ip) { 1267334Skre dev = mp->m_dev; 1277334Skre fs = mp->m_bufp->b_un.b_fs; 1287334Skre ino = ROOTINO; 1297334Skre goto loop; 1307334Skre } 13124Sbill panic("no imt"); 13224Sbill } 1337334Skre if (ip->i_count == 0) { /* ino on free list */ 1347334Skre if (iq = ip->i_freef) 1357334Skre iq->i_freeb = ip->i_freeb; 1367334Skre else 1377334Skre ifreet = ip->i_freeb; 1387334Skre *ip->i_freeb = iq; 1397334Skre ip->i_freef = NULL; 1407334Skre ip->i_freeb = NULL; 1417334Skre } 14224Sbill ip->i_count++; 14324Sbill ip->i_flag |= ILOCK; 14424Sbill return(ip); 14524Sbill } 1467334Skre 1477334Skre if ((ip = ifreeh) == NULL) { 1482933Swnj tablefull("inode"); 14924Sbill u.u_error = ENFILE; 15024Sbill return(NULL); 15124Sbill } 1527334Skre if (iq = ip->i_freef) 1537334Skre iq->i_freeb = &ifreeh; 1547334Skre ifreeh = iq; 1557334Skre ip->i_freef = NULL; 1567334Skre ip->i_freeb = NULL; 1577334Skre /* 1587334Skre * Now to take inode off the hash chain it was on 1597334Skre * (initially, or after an iflush, it is on a "hash chain" 1607334Skre * consisting entirely of itself, and pointed to by no-one, 1617334Skre * but that doesn't matter), and put it on the chain for 1627334Skre * its new (ino, dev) pair 1637334Skre */ 1647335Skre remque(ip); 1657335Skre insque(ip, ih); 1667651Ssam #ifdef QUOTA 1677492Skre dqrele(ip->i_dquot); 1687492Skre #endif 16924Sbill ip->i_dev = dev; 1706569Smckusic ip->i_fs = fs; 17124Sbill ip->i_number = ino; 17224Sbill ip->i_flag = ILOCK; 17324Sbill ip->i_count++; 1746569Smckusic ip->i_lastr = 0; 1756569Smckusic bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize); 17624Sbill /* 17724Sbill * Check I/O errors 17824Sbill */ 1794818Swnj if ((bp->b_flags&B_ERROR) != 0) { 18024Sbill brelse(bp); 1817334Skre /* 1827334Skre * the inode doesn't contain anything useful, so it would 1837334Skre * be misleading to leave it on its hash chain. 1847334Skre * 'iput' will take care of putting it back on the free list. 1857334Skre */ 1867335Skre remque(ip); 1877334Skre ip->i_forw = ip; 1887334Skre ip->i_back = ip; 1897334Skre /* 1907334Skre * we also loose its inumber, just in case (as iput 1917334Skre * doesn't do that any more) - but as it isn't on its 1927334Skre * hash chain, I doubt if this is really necessary .. kre 1937334Skre * (probably the two methods are interchangable) 1947334Skre */ 1957334Skre ip->i_number = 0; 1967651Ssam #ifdef QUOTA 1977492Skre ip->i_dquot = NODQUOT; 1987492Skre #endif 19924Sbill iput(ip); 20024Sbill return(NULL); 20124Sbill } 20224Sbill dp = bp->b_un.b_dino; 2036569Smckusic dp += itoo(fs, ino); 2046569Smckusic ip->i_ic = dp->di_ic; 20524Sbill brelse(bp); 2067651Ssam #ifdef QUOTA 2077492Skre if (ip->i_mode == 0) 2087492Skre ip->i_dquot = NODQUOT; 2097492Skre else 2107492Skre ip->i_dquot = inoquota(ip); 2117492Skre #endif 2126569Smckusic return (ip); 21324Sbill } 21424Sbill 21524Sbill /* 21624Sbill * Decrement reference count of 21724Sbill * an inode structure. 21824Sbill * On the last reference, 21924Sbill * write the inode out and if necessary, 22024Sbill * truncate and deallocate the file. 22124Sbill */ 22224Sbill iput(ip) 2234818Swnj register struct inode *ip; 22424Sbill { 2257118Smckusick 2267118Smckusick if ((ip->i_flag & ILOCK) == 0) 2277118Smckusick panic("iput"); 2287118Smckusick iunlock(ip); 2297118Smckusick irele(ip); 2307118Smckusick } 2317118Smckusick 2327118Smckusick irele(ip) 2337118Smckusick register struct inode *ip; 2347118Smckusick { 23524Sbill register int i, x; 23624Sbill register struct inode *jp; 2376569Smckusic int mode; 23824Sbill 2394818Swnj if (ip->i_count == 1) { 24024Sbill ip->i_flag |= ILOCK; 2414818Swnj if (ip->i_nlink <= 0) { 2427702Ssam itrunc(ip, 0); 2436569Smckusic mode = ip->i_mode; 24424Sbill ip->i_mode = 0; 2457351Skre ip->i_rdev = 0; 24624Sbill ip->i_flag |= IUPD|ICHG; 2476569Smckusic ifree(ip, ip->i_number, mode); 2487651Ssam #ifdef QUOTA 2497492Skre chkiq(ip->i_dev, ip, ip->i_uid, 0); 2507492Skre dqrele(ip->i_dquot); 2517492Skre ip->i_dquot = NODQUOT; 2527492Skre #endif 25324Sbill } 254*8106Sroot IUPDAT(ip, &time.tv_sec, &time.tv_sec, 0); 2557118Smckusick iunlock(ip); 2567334Skre ip->i_flag = 0; 2577334Skre /* 2587334Skre * Put the inode on the end of the free list. 2597334Skre * Possibly in some cases it would be better to 2607334Skre * put the inode at the head of the free list, 2617334Skre * (eg: where i_mode == 0 || i_number == 0) 2627334Skre * but I will think about that later .. kre 2637334Skre * (i_number is rarely 0 - only after an i/o error in iget, 2647334Skre * where i_mode == 0, the inode will probably be wanted 2657334Skre * again soon for an ialloc, so possibly we should keep it) 2667334Skre */ 2677334Skre if (ifreeh) { 2687334Skre *ifreet = ip; 2697334Skre ip->i_freeb = ifreet; 27024Sbill } else { 2717334Skre ifreeh = ip; 2727334Skre ip->i_freeb = &ifreeh; 27324Sbill } 2747334Skre ip->i_freef = NULL; 2757334Skre ifreet = &ip->i_freef; 2767118Smckusick } 27724Sbill ip->i_count--; 27824Sbill } 27924Sbill 28024Sbill /* 28124Sbill * Check accessed and update flags on 28224Sbill * an inode structure. 28324Sbill * If any is on, update the inode 28424Sbill * with the current time. 2851203Sbill * If waitfor is given, then must insure 2861203Sbill * i/o order so wait for write to complete. 28724Sbill */ 2881203Sbill iupdat(ip, ta, tm, waitfor) 2894818Swnj register struct inode *ip; 2904818Swnj time_t *ta, *tm; 2914818Swnj int waitfor; 29224Sbill { 29324Sbill register struct buf *bp; 29424Sbill struct dinode *dp; 2956569Smckusic register struct fs *fp; 29624Sbill 2976569Smckusic fp = ip->i_fs; 2986569Smckusic if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) { 2996569Smckusic if (fp->fs_ronly) 30024Sbill return; 3016569Smckusic bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)), 3026569Smckusic fp->fs_bsize); 30324Sbill if (bp->b_flags & B_ERROR) { 30424Sbill brelse(bp); 30524Sbill return; 30624Sbill } 3074818Swnj if (ip->i_flag&IACC) 3086569Smckusic ip->i_atime = *ta; 3094818Swnj if (ip->i_flag&IUPD) 3106569Smckusic ip->i_mtime = *tm; 3114818Swnj if (ip->i_flag&ICHG) 312*8106Sroot ip->i_ctime = time.tv_sec; 31324Sbill ip->i_flag &= ~(IUPD|IACC|ICHG); 3147343Skre dp = bp->b_un.b_dino + itoo(fp, ip->i_number); 3157343Skre dp->di_ic = ip->i_ic; 3161203Sbill if (waitfor) 3171203Sbill bwrite(bp); 3181203Sbill else 3191203Sbill bdwrite(bp); 32024Sbill } 32124Sbill } 32224Sbill 32324Sbill /* 3247702Ssam * Truncate the inode ip to at most 3257702Ssam * length size. Free affected disk 3267702Ssam * blocks -- the blocks of the file 3277702Ssam * are removed in reverse order. 32824Sbill */ 3297702Ssam itrunc(ip, length) 3304818Swnj register struct inode *ip; 3317702Ssam register int length; 33224Sbill { 33324Sbill register i; 33424Sbill dev_t dev; 33524Sbill daddr_t bn; 3361203Sbill struct inode itmp; 3376569Smckusic register struct fs *fs; 3387651Ssam #ifdef QUOTA 3397492Skre register long cnt = 0; 3407492Skre long tloop(); 3417492Skre #endif 3427606Ssam /* 3437606Ssam * Only plain files, directories and symbolic 3447606Ssam * links contain blocks. 3457606Ssam */ 3467606Ssam i = ip->i_mode & IFMT; 3477606Ssam if (i != IFREG && i != IFDIR && i != IFLNK) 3487606Ssam return; 3497702Ssam if (ip->i_size <= length) 3507702Ssam return; 35124Sbill 3521203Sbill /* 3531203Sbill * Clean inode on disk before freeing blocks 3541203Sbill * to insure no duplicates if system crashes. 3551203Sbill */ 3561203Sbill itmp = *ip; 3577702Ssam itmp.i_size = length; 3586569Smckusic for (i = 0; i < NDADDR; i++) 3596569Smckusic itmp.i_db[i] = 0; 3606569Smckusic for (i = 0; i < NIADDR; i++) 3616569Smckusic itmp.i_ib[i] = 0; 3621203Sbill itmp.i_flag |= ICHG|IUPD; 363*8106Sroot iupdat(&itmp, &time.tv_sec, &time.tv_sec, 1); 3641203Sbill ip->i_flag &= ~(IUPD|IACC|ICHG); 3651203Sbill 3661203Sbill /* 3671203Sbill * Now return blocks to free list... if machine 3681203Sbill * crashes, they will be harmless MISSING blocks. 3691203Sbill */ 37024Sbill dev = ip->i_dev; 3716569Smckusic fs = ip->i_fs; 3726569Smckusic /* 3736569Smckusic * release double indirect block first 3746569Smckusic */ 3756569Smckusic bn = ip->i_ib[NIADDR-1]; 3766569Smckusic if (bn != (daddr_t)0) { 3776569Smckusic ip->i_ib[NIADDR - 1] = (daddr_t)0; 3787651Ssam #ifdef QUOTA 3797492Skre cnt += 3807492Skre #endif 3817492Skre tloop(ip, bn, 1); 3826569Smckusic } 3836569Smckusic /* 3846569Smckusic * release single indirect blocks second 3856569Smckusic */ 3866569Smckusic for (i = NIADDR - 2; i >= 0; i--) { 3876569Smckusic bn = ip->i_ib[i]; 3886569Smckusic if (bn != (daddr_t)0) { 3896569Smckusic ip->i_ib[i] = (daddr_t)0; 3907651Ssam #ifdef QUOTA 3917492Skre cnt += 3927492Skre #endif 3937492Skre tloop(ip, bn, 0); 3946569Smckusic } 3956569Smckusic } 3966569Smckusic /* 3976569Smckusic * finally release direct blocks 3986569Smckusic */ 3996569Smckusic for (i = NDADDR - 1; i>=0; i--) { 4007492Skre register size; 4017492Skre 4026569Smckusic bn = ip->i_db[i]; 4034818Swnj if (bn == (daddr_t)0) 40424Sbill continue; 4056569Smckusic ip->i_db[i] = (daddr_t)0; 4067492Skre fre(ip, bn, size = (off_t)blksize(fs, ip, i)); 4077651Ssam #ifdef QUOTA 4087492Skre cnt += size / DEV_BSIZE; 4097492Skre #endif 41024Sbill } 41124Sbill ip->i_size = 0; 4121203Sbill /* 4131203Sbill * Inode was written and flags updated above. 4141203Sbill * No need to modify flags here. 4151203Sbill */ 4167651Ssam #ifdef QUOTA 4177492Skre (void) chkdq(ip, -cnt, 0); 4187492Skre #endif 41924Sbill } 42024Sbill 4217651Ssam #ifdef QUOTA 4227492Skre long 4237492Skre #endif 4246569Smckusic tloop(ip, bn, indflg) 4256569Smckusic register struct inode *ip; 4266569Smckusic daddr_t bn; 4276569Smckusic int indflg; 42824Sbill { 42924Sbill register i; 43024Sbill register struct buf *bp; 43124Sbill register daddr_t *bap; 4326569Smckusic register struct fs *fs; 43324Sbill daddr_t nb; 4347651Ssam #ifdef QUOTA 4357492Skre register long cnt = 0; 4367492Skre #endif 43724Sbill 43824Sbill bp = NULL; 4396569Smckusic fs = ip->i_fs; 4406569Smckusic for (i = NINDIR(fs) - 1; i >= 0; i--) { 4414818Swnj if (bp == NULL) { 4426569Smckusic bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize); 44324Sbill if (bp->b_flags & B_ERROR) { 44424Sbill brelse(bp); 44524Sbill return; 44624Sbill } 44724Sbill bap = bp->b_un.b_daddr; 44824Sbill } 44924Sbill nb = bap[i]; 4504818Swnj if (nb == (daddr_t)0) 45124Sbill continue; 4527492Skre if (indflg) { 4537651Ssam #ifdef QUOTA 4547492Skre cnt += 4557492Skre #endif 4567492Skre tloop(ip, nb, 0); 4577492Skre } else { 4586569Smckusic fre(ip, nb, fs->fs_bsize); 4597651Ssam #ifdef QUOTA 4607492Skre cnt += fs->fs_bsize / DEV_BSIZE; 4617492Skre #endif 4627492Skre } 46324Sbill } 4644818Swnj if (bp != NULL) 46524Sbill brelse(bp); 4666569Smckusic fre(ip, bn, fs->fs_bsize); 4677651Ssam #ifdef QUOTA 4687492Skre cnt += fs->fs_bsize / DEV_BSIZE; 4697492Skre return(cnt); 4707492Skre #endif 47124Sbill } 47224Sbill 47324Sbill /* 4747334Skre * remove any inodes in the inode cache belonging to dev 4757334Skre * 4767334Skre * There should not be any active ones, return error if any are found 4777334Skre * (nb: this is a user error, not a system err) 4787334Skre * 4797334Skre * Also, count the references to dev by block devices - this really 4807334Skre * has nothing to do with the object of the procedure, but as we have 4817334Skre * to scan the inode table here anyway, we might as well get the 4827334Skre * extra benefit. 4837334Skre * 4847334Skre * this is called from sumount()/sys3.c when dev is being unmounted 4857334Skre */ 4867651Ssam #ifdef QUOTA 4877504Sroot iflush(dev, iq) 4887492Skre dev_t dev; 4897504Sroot struct inode *iq; 4907492Skre #else 4917334Skre iflush(dev) 4927334Skre dev_t dev; 4937492Skre #endif 4947334Skre { 4957335Skre register struct inode *ip; 4967334Skre register open = 0; 4977334Skre 4987334Skre for (ip = inode; ip < inodeNINODE; ip++) { 4997651Ssam #ifdef QUOTA 5007492Skre if (ip != iq && ip->i_dev == dev) 5017492Skre #else 5027334Skre if (ip->i_dev == dev) 5037492Skre #endif 5047334Skre if (ip->i_count) 5057334Skre return(-1); 5067334Skre else { 5077335Skre remque(ip); 5087334Skre ip->i_forw = ip; 5097334Skre ip->i_back = ip; 5107334Skre /* 5117334Skre * as i_count == 0, the inode was on the free 5127334Skre * list already, just leave it there, it will 5137334Skre * fall off the bottom eventually. We could 5147334Skre * perhaps move it to the head of the free 5157334Skre * list, but as umounts are done so 5167334Skre * infrequently, we would gain very little, 5177334Skre * while making the code bigger. 5187334Skre */ 5197651Ssam #ifdef QUOTA 5207492Skre dqrele(ip->i_dquot); 5217492Skre ip->i_dquot = NODQUOT; 5227492Skre #endif 5237334Skre } 5247334Skre else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK && 5257334Skre ip->i_rdev == dev) 5267334Skre open++; 5277334Skre } 5287334Skre return (open); 5297334Skre } 5307334Skre 5314818Swnj #ifdef ilock 5324818Swnj #undef ilock 5333617Sroot #endif 5347118Smckusick #ifdef iunlock 5357118Smckusick #undef iunlock 5363617Sroot #endif 5373617Sroot /* 5384818Swnj * Lock an inode. If its already locked, set the WANT bit and sleep. 5393617Sroot */ 5404818Swnj ilock(ip) 5414818Swnj register struct inode *ip; 5423617Sroot { 5433617Sroot 5444818Swnj while (ip->i_flag&ILOCK) { 5453617Sroot ip->i_flag |= IWANT; 5463617Sroot sleep((caddr_t)ip, PINOD); 5473617Sroot } 5483617Sroot ip->i_flag |= ILOCK; 5493617Sroot } 5503617Sroot 5513617Sroot /* 5524818Swnj * Unlock an inode. If WANT bit is on, wakeup. 5533617Sroot */ 5547118Smckusick iunlock(ip) 5554818Swnj register struct inode *ip; 5563617Sroot { 5573617Sroot 5583617Sroot ip->i_flag &= ~ILOCK; 5594818Swnj if (ip->i_flag&IWANT) { 5603617Sroot ip->i_flag &= ~IWANT; 5613617Sroot wakeup((caddr_t)ip); 5623617Sroot } 5633617Sroot } 564