1*7606Ssam /* lfs_inode.c 4.21 82/07/30 */ 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" 137504Sroot #ifdef QUOTA 147504Sroot #include "../h/quota.h" 157504Sroot #endif 1624Sbill 1724Sbill #define INOHSZ 63 187334Skre #if ((INOHSZ&(INOHSZ-1)) == 0) 197334Skre #define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1)) 207334Skre #else 2124Sbill #define INOHASH(dev,ino) (((dev)+(ino))%INOHSZ) 227334Skre #endif 2324Sbill 247334Skre union ihead { /* inode LRU cache, Chris Maltby */ 257334Skre union ihead *ih_head[2]; 267334Skre struct inode *ih_chain[2]; 277334Skre } ihead[INOHSZ]; 287334Skre 297334Skre struct inode *ifreeh, **ifreet; 307334Skre 3124Sbill /* 3224Sbill * Initialize hash links for inodes 3324Sbill * and build inode free list. 3424Sbill */ 3524Sbill ihinit() 3624Sbill { 3724Sbill register int i; 382737Swnj register struct inode *ip = inode; 397334Skre register union ihead *ih = ihead; 4024Sbill 417334Skre for (i = INOHSZ; --i >= 0; ih++) { 427334Skre ih->ih_head[0] = ih; 437334Skre ih->ih_head[1] = ih; 447334Skre } 457334Skre ifreeh = ip; 467334Skre ifreet = &ip->i_freef; 477334Skre ip->i_freeb = &ifreeh; 487334Skre ip->i_forw = ip; 497334Skre ip->i_back = ip; 507334Skre for (i = ninode; --i > 0; ) { 517334Skre ++ip; 527334Skre ip->i_forw = ip; 537334Skre ip->i_back = ip; 547334Skre *ifreet = ip; 557334Skre ip->i_freeb = ifreet; 567334Skre ifreet = &ip->i_freef; 577334Skre } 587334Skre ip->i_freef = NULL; 5924Sbill } 6024Sbill 617334Skre #ifdef notdef 6224Sbill /* 637334Skre * Find an inode if it is incore. 647334Skre * This is the equivalent, for inodes, 657334Skre * of ``incore'' in bio.c or ``pfind'' in subr.c. 667334Skre */ 677334Skre struct inode * 687334Skre ifind(dev, ino) 697334Skre dev_t dev; 707334Skre ino_t ino; 717334Skre { 727334Skre register struct inode *ip; 737334Skre register union ihead *ih; 747334Skre 757334Skre ih = &ihead[INOHASH(dev, ino)]; 767334Skre for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) 777334Skre if (ino==ip->i_number && dev==ip->i_dev) 787334Skre return (ip); 797334Skre return ((struct inode *)0); 807334Skre } 817334Skre #endif notdef 827334Skre 837334Skre /* 8424Sbill * Look up an inode by device,inumber. 8524Sbill * If it is in core (in the inode structure), 8624Sbill * honor the locking protocol. 8724Sbill * If it is not in core, read it in from the 8824Sbill * specified device. 8924Sbill * If the inode is mounted on, perform 9024Sbill * the indicated indirection. 9124Sbill * In all cases, a pointer to a locked 9224Sbill * inode structure is returned. 9324Sbill * 9424Sbill * panic: no imt -- if the mounted file 9524Sbill * system is not in the mount table. 9624Sbill * "cannot happen" 9724Sbill */ 9824Sbill struct inode * 996569Smckusic iget(dev, fs, ino) 1004818Swnj dev_t dev; 1016569Smckusic register struct fs *fs; 1024818Swnj ino_t ino; 10324Sbill { 1047335Skre register struct inode *ip; 1057335Skre register union ihead *ih; 10624Sbill register struct mount *mp; 10724Sbill register struct buf *bp; 10824Sbill register struct dinode *dp; 1097334Skre register struct inode *iq; 11024Sbill 11124Sbill loop: 1126569Smckusic if (getfs(dev) != fs) 1136569Smckusic panic("iget: bad fs"); 1147334Skre ih = &ihead[INOHASH(dev, ino)]; 1157334Skre for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) 1164818Swnj if (ino == ip->i_number && dev == ip->i_dev) { 1174818Swnj if ((ip->i_flag&ILOCK) != 0) { 11824Sbill ip->i_flag |= IWANT; 11924Sbill sleep((caddr_t)ip, PINOD); 12024Sbill goto loop; 12124Sbill } 1224818Swnj if ((ip->i_flag&IMOUNT) != 0) { 1236569Smckusic for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 1247334Skre if(mp->m_inodp == ip) { 1257334Skre dev = mp->m_dev; 1267334Skre fs = mp->m_bufp->b_un.b_fs; 1277334Skre ino = ROOTINO; 1287334Skre goto loop; 1297334Skre } 13024Sbill panic("no imt"); 13124Sbill } 1327334Skre if (ip->i_count == 0) { /* ino on free list */ 1337334Skre if (iq = ip->i_freef) 1347334Skre iq->i_freeb = ip->i_freeb; 1357334Skre else 1367334Skre ifreet = ip->i_freeb; 1377334Skre *ip->i_freeb = iq; 1387334Skre ip->i_freef = NULL; 1397334Skre ip->i_freeb = NULL; 1407334Skre } 14124Sbill ip->i_count++; 14224Sbill ip->i_flag |= ILOCK; 14324Sbill return(ip); 14424Sbill } 1457334Skre 1467334Skre if ((ip = ifreeh) == NULL) { 1472933Swnj tablefull("inode"); 14824Sbill u.u_error = ENFILE; 14924Sbill return(NULL); 15024Sbill } 1517334Skre if (iq = ip->i_freef) 1527334Skre iq->i_freeb = &ifreeh; 1537334Skre ifreeh = iq; 1547334Skre ip->i_freef = NULL; 1557334Skre ip->i_freeb = NULL; 1567334Skre /* 1577334Skre * Now to take inode off the hash chain it was on 1587334Skre * (initially, or after an iflush, it is on a "hash chain" 1597334Skre * consisting entirely of itself, and pointed to by no-one, 1607334Skre * but that doesn't matter), and put it on the chain for 1617334Skre * its new (ino, dev) pair 1627334Skre */ 1637335Skre remque(ip); 1647335Skre insque(ip, ih); 1657492Skre #ifdef QUOTA 1667492Skre dqrele(ip->i_dquot); 1677492Skre #endif 16824Sbill ip->i_dev = dev; 1696569Smckusic ip->i_fs = fs; 17024Sbill ip->i_number = ino; 17124Sbill ip->i_flag = ILOCK; 17224Sbill ip->i_count++; 1736569Smckusic ip->i_lastr = 0; 1746569Smckusic bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize); 17524Sbill /* 17624Sbill * Check I/O errors 17724Sbill */ 1784818Swnj if ((bp->b_flags&B_ERROR) != 0) { 17924Sbill brelse(bp); 1807334Skre /* 1817334Skre * the inode doesn't contain anything useful, so it would 1827334Skre * be misleading to leave it on its hash chain. 1837334Skre * 'iput' will take care of putting it back on the free list. 1847334Skre */ 1857335Skre remque(ip); 1867334Skre ip->i_forw = ip; 1877334Skre ip->i_back = ip; 1887334Skre /* 1897334Skre * we also loose its inumber, just in case (as iput 1907334Skre * doesn't do that any more) - but as it isn't on its 1917334Skre * hash chain, I doubt if this is really necessary .. kre 1927334Skre * (probably the two methods are interchangable) 1937334Skre */ 1947334Skre ip->i_number = 0; 1957492Skre #ifdef QUOTA 1967492Skre ip->i_dquot = NODQUOT; 1977492Skre #endif 19824Sbill iput(ip); 19924Sbill return(NULL); 20024Sbill } 20124Sbill dp = bp->b_un.b_dino; 2026569Smckusic dp += itoo(fs, ino); 2036569Smckusic ip->i_ic = dp->di_ic; 20424Sbill brelse(bp); 2057492Skre #ifdef QUOTA 2067492Skre if (ip->i_mode == 0) 2077492Skre ip->i_dquot = NODQUOT; 2087492Skre else 2097492Skre ip->i_dquot = inoquota(ip); 2107492Skre #endif 2116569Smckusic return (ip); 21224Sbill } 21324Sbill 21424Sbill /* 21524Sbill * Decrement reference count of 21624Sbill * an inode structure. 21724Sbill * On the last reference, 21824Sbill * write the inode out and if necessary, 21924Sbill * truncate and deallocate the file. 22024Sbill */ 22124Sbill iput(ip) 2224818Swnj register struct inode *ip; 22324Sbill { 2247118Smckusick 2257118Smckusick if ((ip->i_flag & ILOCK) == 0) 2267118Smckusick panic("iput"); 2277118Smckusick iunlock(ip); 2287118Smckusick irele(ip); 2297118Smckusick } 2307118Smckusick 2317118Smckusick irele(ip) 2327118Smckusick register struct inode *ip; 2337118Smckusick { 23424Sbill register int i, x; 23524Sbill register struct inode *jp; 2366569Smckusic int mode; 23724Sbill 2384818Swnj if (ip->i_count == 1) { 23924Sbill ip->i_flag |= ILOCK; 2404818Swnj if (ip->i_nlink <= 0) { 24124Sbill itrunc(ip); 2426569Smckusic mode = ip->i_mode; 24324Sbill ip->i_mode = 0; 2447351Skre ip->i_rdev = 0; 24524Sbill ip->i_flag |= IUPD|ICHG; 2466569Smckusic ifree(ip, ip->i_number, mode); 2477492Skre #ifdef QUOTA 2487492Skre chkiq(ip->i_dev, ip, ip->i_uid, 0); 2497492Skre dqrele(ip->i_dquot); 2507492Skre ip->i_dquot = NODQUOT; 2517492Skre #endif 25224Sbill } 2531203Sbill IUPDAT(ip, &time, &time, 0); 2547118Smckusick iunlock(ip); 2557334Skre ip->i_flag = 0; 2567334Skre /* 2577334Skre * Put the inode on the end of the free list. 2587334Skre * Possibly in some cases it would be better to 2597334Skre * put the inode at the head of the free list, 2607334Skre * (eg: where i_mode == 0 || i_number == 0) 2617334Skre * but I will think about that later .. kre 2627334Skre * (i_number is rarely 0 - only after an i/o error in iget, 2637334Skre * where i_mode == 0, the inode will probably be wanted 2647334Skre * again soon for an ialloc, so possibly we should keep it) 2657334Skre */ 2667334Skre if (ifreeh) { 2677334Skre *ifreet = ip; 2687334Skre ip->i_freeb = ifreet; 26924Sbill } else { 2707334Skre ifreeh = ip; 2717334Skre ip->i_freeb = &ifreeh; 27224Sbill } 2737334Skre ip->i_freef = NULL; 2747334Skre ifreet = &ip->i_freef; 2757118Smckusick } 27624Sbill ip->i_count--; 27724Sbill } 27824Sbill 27924Sbill /* 28024Sbill * Check accessed and update flags on 28124Sbill * an inode structure. 28224Sbill * If any is on, update the inode 28324Sbill * with the current time. 2841203Sbill * If waitfor is given, then must insure 2851203Sbill * i/o order so wait for write to complete. 28624Sbill */ 2871203Sbill iupdat(ip, ta, tm, waitfor) 2884818Swnj register struct inode *ip; 2894818Swnj time_t *ta, *tm; 2904818Swnj int waitfor; 29124Sbill { 29224Sbill register struct buf *bp; 29324Sbill struct dinode *dp; 2946569Smckusic register struct fs *fp; 29524Sbill 2966569Smckusic fp = ip->i_fs; 2976569Smckusic if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) { 2986569Smckusic if (fp->fs_ronly) 29924Sbill return; 3006569Smckusic bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)), 3016569Smckusic fp->fs_bsize); 30224Sbill if (bp->b_flags & B_ERROR) { 30324Sbill brelse(bp); 30424Sbill return; 30524Sbill } 3064818Swnj if (ip->i_flag&IACC) 3076569Smckusic ip->i_atime = *ta; 3084818Swnj if (ip->i_flag&IUPD) 3096569Smckusic ip->i_mtime = *tm; 3104818Swnj if (ip->i_flag&ICHG) 3116569Smckusic ip->i_ctime = time; 31224Sbill ip->i_flag &= ~(IUPD|IACC|ICHG); 3137343Skre dp = bp->b_un.b_dino + itoo(fp, ip->i_number); 3147343Skre dp->di_ic = ip->i_ic; 3151203Sbill if (waitfor) 3161203Sbill bwrite(bp); 3171203Sbill else 3181203Sbill bdwrite(bp); 31924Sbill } 32024Sbill } 32124Sbill 32224Sbill /* 32324Sbill * Free all the disk blocks associated 32424Sbill * with the specified inode structure. 32524Sbill * The blocks of the file are removed 3267533Sroot * in reverse order. 32724Sbill */ 32824Sbill itrunc(ip) 3294818Swnj register struct inode *ip; 33024Sbill { 33124Sbill register i; 33224Sbill dev_t dev; 33324Sbill daddr_t bn; 3341203Sbill struct inode itmp; 3356569Smckusic register struct fs *fs; 3367492Skre #ifdef QUOTA 3377492Skre register long cnt = 0; 3387492Skre long tloop(); 3397492Skre #endif 340*7606Ssam /* 341*7606Ssam * Only plain files, directories and symbolic 342*7606Ssam * links contain blocks. 343*7606Ssam */ 344*7606Ssam i = ip->i_mode & IFMT; 345*7606Ssam if (i != IFREG && i != IFDIR && i != IFLNK) 346*7606Ssam return; 34724Sbill 3481203Sbill /* 3491203Sbill * Clean inode on disk before freeing blocks 3501203Sbill * to insure no duplicates if system crashes. 3511203Sbill */ 3521203Sbill itmp = *ip; 3531203Sbill itmp.i_size = 0; 3546569Smckusic for (i = 0; i < NDADDR; i++) 3556569Smckusic itmp.i_db[i] = 0; 3566569Smckusic for (i = 0; i < NIADDR; i++) 3576569Smckusic itmp.i_ib[i] = 0; 3581203Sbill itmp.i_flag |= ICHG|IUPD; 3591203Sbill iupdat(&itmp, &time, &time, 1); 3601203Sbill ip->i_flag &= ~(IUPD|IACC|ICHG); 3611203Sbill 3621203Sbill /* 3631203Sbill * Now return blocks to free list... if machine 3641203Sbill * crashes, they will be harmless MISSING blocks. 3651203Sbill */ 36624Sbill dev = ip->i_dev; 3676569Smckusic fs = ip->i_fs; 3686569Smckusic /* 3696569Smckusic * release double indirect block first 3706569Smckusic */ 3716569Smckusic bn = ip->i_ib[NIADDR-1]; 3726569Smckusic if (bn != (daddr_t)0) { 3736569Smckusic ip->i_ib[NIADDR - 1] = (daddr_t)0; 3747492Skre #ifdef QUOTA 3757492Skre cnt += 3767492Skre #endif 3777492Skre tloop(ip, bn, 1); 3786569Smckusic } 3796569Smckusic /* 3806569Smckusic * release single indirect blocks second 3816569Smckusic */ 3826569Smckusic for (i = NIADDR - 2; i >= 0; i--) { 3836569Smckusic bn = ip->i_ib[i]; 3846569Smckusic if (bn != (daddr_t)0) { 3856569Smckusic ip->i_ib[i] = (daddr_t)0; 3867492Skre #ifdef QUOTA 3877492Skre cnt += 3887492Skre #endif 3897492Skre tloop(ip, bn, 0); 3906569Smckusic } 3916569Smckusic } 3926569Smckusic /* 3936569Smckusic * finally release direct blocks 3946569Smckusic */ 3956569Smckusic for (i = NDADDR - 1; i>=0; i--) { 3967492Skre register size; 3977492Skre 3986569Smckusic bn = ip->i_db[i]; 3994818Swnj if (bn == (daddr_t)0) 40024Sbill continue; 4016569Smckusic ip->i_db[i] = (daddr_t)0; 4027492Skre fre(ip, bn, size = (off_t)blksize(fs, ip, i)); 4037492Skre #ifdef QUOTA 4047492Skre cnt += size / DEV_BSIZE; 4057492Skre #endif 40624Sbill } 40724Sbill ip->i_size = 0; 4081203Sbill /* 4091203Sbill * Inode was written and flags updated above. 4101203Sbill * No need to modify flags here. 4111203Sbill */ 4127492Skre #ifdef QUOTA 4137492Skre (void) chkdq(ip, -cnt, 0); 4147492Skre #endif 41524Sbill } 41624Sbill 4177492Skre #ifdef QUOTA 4187492Skre long 4197492Skre #endif 4206569Smckusic tloop(ip, bn, indflg) 4216569Smckusic register struct inode *ip; 4226569Smckusic daddr_t bn; 4236569Smckusic int indflg; 42424Sbill { 42524Sbill register i; 42624Sbill register struct buf *bp; 42724Sbill register daddr_t *bap; 4286569Smckusic register struct fs *fs; 42924Sbill daddr_t nb; 4307492Skre #ifdef QUOTA 4317492Skre register long cnt = 0; 4327492Skre #endif 43324Sbill 43424Sbill bp = NULL; 4356569Smckusic fs = ip->i_fs; 4366569Smckusic for (i = NINDIR(fs) - 1; i >= 0; i--) { 4374818Swnj if (bp == NULL) { 4386569Smckusic bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize); 43924Sbill if (bp->b_flags & B_ERROR) { 44024Sbill brelse(bp); 44124Sbill return; 44224Sbill } 44324Sbill bap = bp->b_un.b_daddr; 44424Sbill } 44524Sbill nb = bap[i]; 4464818Swnj if (nb == (daddr_t)0) 44724Sbill continue; 4487492Skre if (indflg) { 4497492Skre #ifdef QUOTA 4507492Skre cnt += 4517492Skre #endif 4527492Skre tloop(ip, nb, 0); 4537492Skre } else { 4546569Smckusic fre(ip, nb, fs->fs_bsize); 4557492Skre #ifdef QUOTA 4567492Skre cnt += fs->fs_bsize / DEV_BSIZE; 4577492Skre #endif 4587492Skre } 45924Sbill } 4604818Swnj if (bp != NULL) 46124Sbill brelse(bp); 4626569Smckusic fre(ip, bn, fs->fs_bsize); 4637492Skre #ifdef QUOTA 4647492Skre cnt += fs->fs_bsize / DEV_BSIZE; 4657492Skre return(cnt); 4667492Skre #endif 46724Sbill } 46824Sbill 46924Sbill /* 4707334Skre * remove any inodes in the inode cache belonging to dev 4717334Skre * 4727334Skre * There should not be any active ones, return error if any are found 4737334Skre * (nb: this is a user error, not a system err) 4747334Skre * 4757334Skre * Also, count the references to dev by block devices - this really 4767334Skre * has nothing to do with the object of the procedure, but as we have 4777334Skre * to scan the inode table here anyway, we might as well get the 4787334Skre * extra benefit. 4797334Skre * 4807334Skre * this is called from sumount()/sys3.c when dev is being unmounted 4817334Skre */ 4827492Skre #ifdef QUOTA 4837504Sroot iflush(dev, iq) 4847492Skre dev_t dev; 4857504Sroot struct inode *iq; 4867492Skre #else 4877334Skre iflush(dev) 4887334Skre dev_t dev; 4897492Skre #endif 4907334Skre { 4917335Skre register struct inode *ip; 4927334Skre register open = 0; 4937334Skre 4947334Skre for (ip = inode; ip < inodeNINODE; ip++) { 4957492Skre #ifdef QUOTA 4967492Skre if (ip != iq && ip->i_dev == dev) 4977492Skre #else 4987334Skre if (ip->i_dev == dev) 4997492Skre #endif 5007334Skre if (ip->i_count) 5017334Skre return(-1); 5027334Skre else { 5037335Skre remque(ip); 5047334Skre ip->i_forw = ip; 5057334Skre ip->i_back = ip; 5067334Skre /* 5077334Skre * as i_count == 0, the inode was on the free 5087334Skre * list already, just leave it there, it will 5097334Skre * fall off the bottom eventually. We could 5107334Skre * perhaps move it to the head of the free 5117334Skre * list, but as umounts are done so 5127334Skre * infrequently, we would gain very little, 5137334Skre * while making the code bigger. 5147334Skre */ 5157492Skre #ifdef QUOTA 5167492Skre dqrele(ip->i_dquot); 5177492Skre ip->i_dquot = NODQUOT; 5187492Skre #endif 5197334Skre } 5207334Skre else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK && 5217334Skre ip->i_rdev == dev) 5227334Skre open++; 5237334Skre } 5247334Skre return (open); 5257334Skre } 5267334Skre 5274818Swnj #ifdef ilock 5284818Swnj #undef ilock 5293617Sroot #endif 5307118Smckusick #ifdef iunlock 5317118Smckusick #undef iunlock 5323617Sroot #endif 5333617Sroot /* 5344818Swnj * Lock an inode. If its already locked, set the WANT bit and sleep. 5353617Sroot */ 5364818Swnj ilock(ip) 5374818Swnj register struct inode *ip; 5383617Sroot { 5393617Sroot 5404818Swnj while (ip->i_flag&ILOCK) { 5413617Sroot ip->i_flag |= IWANT; 5423617Sroot sleep((caddr_t)ip, PINOD); 5433617Sroot } 5443617Sroot ip->i_flag |= ILOCK; 5453617Sroot } 5463617Sroot 5473617Sroot /* 5484818Swnj * Unlock an inode. If WANT bit is on, wakeup. 5493617Sroot */ 5507118Smckusick iunlock(ip) 5514818Swnj register struct inode *ip; 5523617Sroot { 5533617Sroot 5543617Sroot ip->i_flag &= ~ILOCK; 5554818Swnj if (ip->i_flag&IWANT) { 5563617Sroot ip->i_flag &= ~IWANT; 5573617Sroot wakeup((caddr_t)ip); 5583617Sroot } 5593617Sroot } 560