1*9165Ssam /* lfs_inode.c 4.31 82/11/13 */ 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" 127651Ssam #ifdef QUOTA 137504Sroot #include "../h/quota.h" 147504Sroot #endif 158106Sroot #include "../h/kernel.h" 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) { 1178452Sroot if ((ip->i_flag&ILOCKED) != 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++; 1428452Sroot ip->i_flag |= ILOCKED; 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); 1657651Ssam #ifdef QUOTA 1667492Skre dqrele(ip->i_dquot); 1677492Skre #endif 16824Sbill ip->i_dev = dev; 1696569Smckusic ip->i_fs = fs; 17024Sbill ip->i_number = ino; 1718452Sroot ip->i_flag = ILOCKED; 17224Sbill ip->i_count++; 1736569Smckusic ip->i_lastr = 0; 1748618Sroot bp = bread(dev, fsbtodb(fs, itod(fs, ino)), (int)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; 1957651Ssam #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); 2057651Ssam #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 2258452Sroot if ((ip->i_flag & ILOCKED) == 0) 2267118Smckusick panic("iput"); 2277118Smckusick iunlock(ip); 2287118Smckusick irele(ip); 2297118Smckusick } 2307118Smckusick 2317118Smckusick irele(ip) 2327118Smckusick register struct inode *ip; 2337118Smckusick { 2346569Smckusic int mode; 23524Sbill 2364818Swnj if (ip->i_count == 1) { 2378452Sroot ip->i_flag |= ILOCKED; 2384818Swnj if (ip->i_nlink <= 0) { 239*9165Ssam itrunc(ip, (u_long)0); 2406569Smckusic mode = ip->i_mode; 24124Sbill ip->i_mode = 0; 2427351Skre ip->i_rdev = 0; 24324Sbill ip->i_flag |= IUPD|ICHG; 2446569Smckusic ifree(ip, ip->i_number, mode); 2457651Ssam #ifdef QUOTA 246*9165Ssam (void)chkiq(ip->i_dev, ip, ip->i_uid, 0); 2477492Skre dqrele(ip->i_dquot); 2487492Skre ip->i_dquot = NODQUOT; 2497492Skre #endif 25024Sbill } 2518671Sroot IUPDAT(ip, &time, &time, 0); 2527118Smckusick iunlock(ip); 2537334Skre ip->i_flag = 0; 2547334Skre /* 2557334Skre * Put the inode on the end of the free list. 2567334Skre * Possibly in some cases it would be better to 2577334Skre * put the inode at the head of the free list, 2587334Skre * (eg: where i_mode == 0 || i_number == 0) 2597334Skre * but I will think about that later .. kre 2607334Skre * (i_number is rarely 0 - only after an i/o error in iget, 2617334Skre * where i_mode == 0, the inode will probably be wanted 2627334Skre * again soon for an ialloc, so possibly we should keep it) 2637334Skre */ 2647334Skre if (ifreeh) { 2657334Skre *ifreet = ip; 2667334Skre ip->i_freeb = ifreet; 26724Sbill } else { 2687334Skre ifreeh = ip; 2697334Skre ip->i_freeb = &ifreeh; 27024Sbill } 2717334Skre ip->i_freef = NULL; 2727334Skre ifreet = &ip->i_freef; 2737118Smckusick } 27424Sbill ip->i_count--; 27524Sbill } 27624Sbill 27724Sbill /* 27824Sbill * Check accessed and update flags on 27924Sbill * an inode structure. 28024Sbill * If any is on, update the inode 28124Sbill * with the current time. 2821203Sbill * If waitfor is given, then must insure 2831203Sbill * i/o order so wait for write to complete. 28424Sbill */ 2851203Sbill iupdat(ip, ta, tm, waitfor) 2864818Swnj register struct inode *ip; 2878630Sroot struct timeval *ta, *tm; 2884818Swnj int waitfor; 28924Sbill { 29024Sbill register struct buf *bp; 29124Sbill struct dinode *dp; 2926569Smckusic register struct fs *fp; 29324Sbill 2946569Smckusic fp = ip->i_fs; 2956569Smckusic if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) { 2966569Smckusic if (fp->fs_ronly) 29724Sbill return; 2986569Smckusic bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)), 2998618Sroot (int)fp->fs_bsize); 30024Sbill if (bp->b_flags & B_ERROR) { 30124Sbill brelse(bp); 30224Sbill return; 30324Sbill } 3044818Swnj if (ip->i_flag&IACC) 3058630Sroot ip->i_atime = ta->tv_sec; 3064818Swnj if (ip->i_flag&IUPD) 3078630Sroot ip->i_mtime = tm->tv_sec; 3084818Swnj if (ip->i_flag&ICHG) 3098106Sroot ip->i_ctime = time.tv_sec; 31024Sbill ip->i_flag &= ~(IUPD|IACC|ICHG); 3117343Skre dp = bp->b_un.b_dino + itoo(fp, ip->i_number); 3127343Skre dp->di_ic = ip->i_ic; 3131203Sbill if (waitfor) 3141203Sbill bwrite(bp); 3151203Sbill else 3161203Sbill bdwrite(bp); 31724Sbill } 31824Sbill } 31924Sbill 32024Sbill /* 3217702Ssam * Truncate the inode ip to at most 3227702Ssam * length size. Free affected disk 3237702Ssam * blocks -- the blocks of the file 3247702Ssam * are removed in reverse order. 32524Sbill */ 3267702Ssam itrunc(ip, length) 3274818Swnj register struct inode *ip; 328*9165Ssam u_long length; 32924Sbill { 33024Sbill register i; 331*9165Ssam register daddr_t lastblock; 332*9165Ssam daddr_t bn, lastdiblock, lastsiblock; 3336569Smckusic register struct fs *fs; 334*9165Ssam int j; 3357651Ssam #ifdef QUOTA 336*9165Ssam long blocksreleased = 0, nblocks; 337*9165Ssam long indirtrunc(); 3387492Skre #endif 339*9165Ssam 340*9165Ssam if (ip->i_size <= length) 341*9165Ssam return; 342*9165Ssam #ifdef notdef 343*9165Ssam /* this is superfluous given size check above */ 3447606Ssam i = ip->i_mode & IFMT; 345*9165Ssam if (i != IFREG && i != IFDIR && i != IFLNK) { 346*9165Ssam printf("itrunc: i# %d, size %d\n", ip->i_number, ip->i_size); 3477606Ssam return; 348*9165Ssam } 349*9165Ssam #endif 3501203Sbill /* 351*9165Ssam * Update size of file on disk before 352*9165Ssam * we start freeing blocks. If we crash 353*9165Ssam * while free'ing blocks below, the file 354*9165Ssam * size will be believed and the blocks 355*9165Ssam * returned to the free list. 356*9165Ssam * After updating the copy on disk we 357*9165Ssam * put the old size back so macros like 358*9165Ssam * blksize will work. 3591203Sbill */ 360*9165Ssam j = ip->i_size; 361*9165Ssam ip->i_size = length; 362*9165Ssam ip->i_flag |= ICHG|IUPD; 363*9165Ssam iupdat(ip, &time, &time, 1); 364*9165Ssam ip->i_size = j; 3651203Sbill 3661203Sbill /* 367*9165Ssam * Calculate last direct, single indirect and 368*9165Ssam * double indirect block (if any) which we want 369*9165Ssam * to keep. Lastblock is -1 when the file is 370*9165Ssam * truncated to 0. 3711203Sbill */ 3726569Smckusic fs = ip->i_fs; 373*9165Ssam lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1; 374*9165Ssam lastsiblock = lastblock - NDADDR; 375*9165Ssam lastdiblock = lastsiblock - NINDIR(fs); 376*9165Ssam #ifdef QUOTA 377*9165Ssam nblocks = fs->fs_bsize / DEV_BSIZE; 378*9165Ssam #endif 3796569Smckusic /* 380*9165Ssam * Double indirect block first 3816569Smckusic */ 382*9165Ssam bn = ip->i_ib[NIADDR - 1]; 383*9165Ssam if (bn != 0) { 384*9165Ssam /* 385*9165Ssam * If lastdiblock is negative, it's value 386*9165Ssam * is meaningless; in this case we set it to 387*9165Ssam * -NINDIR(fs) so calculations performed in 388*9165Ssam * indirtrunc come out right. 389*9165Ssam */ 390*9165Ssam if (lastdiblock < 0) 391*9165Ssam lastdiblock -= lastsiblock; 3927651Ssam #ifdef QUOTA 393*9165Ssam blocksreleased += 3947492Skre #endif 395*9165Ssam indirtrunc(ip, bn, lastdiblock, 1); 396*9165Ssam if (lastdiblock < 0) { 397*9165Ssam ip->i_ib[NIADDR - 1] = 0; 398*9165Ssam free(ip, bn, (off_t)fs->fs_bsize); 399*9165Ssam #ifdef QUOTA 400*9165Ssam blocksreleased += nblocks; 401*9165Ssam #endif 402*9165Ssam } 4036569Smckusic } 404*9165Ssam if (lastdiblock >= 0) 405*9165Ssam goto done; 4066569Smckusic /* 407*9165Ssam * Single indirect blocks second. 408*9165Ssam * First, those which can be totally 409*9165Ssam * zapped, then possibly one which 410*9165Ssam * needs to be partially cleared. 4116569Smckusic */ 412*9165Ssam j = lastsiblock < 0 ? -1 : lastsiblock / NINDIR(fs); 413*9165Ssam for (i = NIADDR - 2; i > j; i--) { 4146569Smckusic bn = ip->i_ib[i]; 415*9165Ssam if (bn != 0) { 4167651Ssam #ifdef QUOTA 417*9165Ssam blocksreleased += nblocks + 4187492Skre #endif 419*9165Ssam indirtrunc(ip, bn, (daddr_t)-1, 0); 420*9165Ssam ip->i_ib[i] = 0; 421*9165Ssam free(ip, bn, (off_t)fs->fs_bsize); 4226569Smckusic } 4236569Smckusic } 424*9165Ssam if (lastsiblock >= 0) { 425*9165Ssam bn = ip->i_ib[j]; 426*9165Ssam if (bn != 0) 427*9165Ssam #ifdef QUOTA 428*9165Ssam blocksreleased += 429*9165Ssam #endif 430*9165Ssam indirtrunc(ip, bn, lastsiblock, 0); 431*9165Ssam goto done; 432*9165Ssam } 4336569Smckusic /* 434*9165Ssam * All whole direct blocks. 4356569Smckusic */ 436*9165Ssam for (i = NDADDR - 1; i > lastblock; i--) { 437*9165Ssam register int size; 438*9165Ssam 4396569Smckusic bn = ip->i_db[i]; 440*9165Ssam if (bn == 0) 44124Sbill continue; 442*9165Ssam ip->i_db[i] = 0; 443*9165Ssam size = (off_t)blksize(fs, ip, i); 444*9165Ssam free(ip, bn, size); 445*9165Ssam #ifdef QUOTA 446*9165Ssam blocksreleased += size / DEV_BSIZE; 4477492Skre #endif 44824Sbill } 4491203Sbill /* 450*9165Ssam * Finally, look for a change in size of the 451*9165Ssam * last direct block; release any frags. 4521203Sbill */ 453*9165Ssam if (lastblock >= 0 && ip->i_db[lastblock] != 0) { 454*9165Ssam /* 455*9165Ssam * Calculate amount of space we're giving 456*9165Ssam * back as old block size minus new block size. 457*9165Ssam */ 458*9165Ssam i = blksize(fs, ip, lastblock); 459*9165Ssam ip->i_size = length; 460*9165Ssam i = i - blksize(fs, ip, lastblock); 461*9165Ssam if (i > 0) { 462*9165Ssam /* 463*9165Ssam * Block number of space to be free'd is 464*9165Ssam * the old block # plus the number of frags 465*9165Ssam * required for the storage we're keeping. 466*9165Ssam */ 467*9165Ssam bn = ip->i_db[lastblock] + 468*9165Ssam numfrags(fs, fs->fs_bsize - i); 469*9165Ssam free(ip, bn, i); 4707651Ssam #ifdef QUOTA 471*9165Ssam blocksreleased += i / DEV_BSIZE; 4727492Skre #endif 473*9165Ssam } 474*9165Ssam } 475*9165Ssam done: 476*9165Ssam /* 477*9165Ssam * Finished free'ing blocks, complete 478*9165Ssam * inode update to reflect new length. 479*9165Ssam */ 480*9165Ssam #ifdef QUOTA 481*9165Ssam (void) chkdq(ip, -blocksreleased, 0); 482*9165Ssam #endif 483*9165Ssam ip->i_size = length; 484*9165Ssam ip->i_flag |= ICHG|IUPD; 485*9165Ssam iupdat(ip, &time, &time, 1); 48624Sbill } 48724Sbill 488*9165Ssam /* 489*9165Ssam * Release blocks associated with the inode ip and 490*9165Ssam * stored in the indirect block bn. Blocks are free'd 491*9165Ssam * in LIFO order up to (but not including) lastbn. If 492*9165Ssam * doubleindirect is indicated, this block is a double 493*9165Ssam * indirect block and recursive calls to indirtrunc must 494*9165Ssam * be used to cleanse single indirect blocks instead of 495*9165Ssam * a simple free. 496*9165Ssam */ 4977651Ssam #ifdef QUOTA 4987492Skre long 4997492Skre #endif 500*9165Ssam indirtrunc(ip, bn, lastbn, doubleindirect) 5016569Smckusic register struct inode *ip; 502*9165Ssam daddr_t bn, lastbn; 503*9165Ssam int doubleindirect; 50424Sbill { 505*9165Ssam register int i; 506*9165Ssam struct buf *bp; 50724Sbill register daddr_t *bap; 5086569Smckusic register struct fs *fs; 509*9165Ssam daddr_t nb, last; 5107651Ssam #ifdef QUOTA 511*9165Ssam int blocksreleased = 0, nblocks; 5127492Skre #endif 51324Sbill 51424Sbill bp = NULL; 5156569Smckusic fs = ip->i_fs; 516*9165Ssam last = lastbn; 517*9165Ssam if (doubleindirect) 518*9165Ssam last /= NINDIR(fs); 519*9165Ssam #ifdef QUOTA 520*9165Ssam nblocks = fs->fs_bsize / DEV_BSIZE; 521*9165Ssam #endif 522*9165Ssam for (i = NINDIR(fs) - 1; i > last; i--) { 5234818Swnj if (bp == NULL) { 524*9165Ssam struct buf *copy; 525*9165Ssam 526*9165Ssam copy = geteblk((int)fs->fs_bsize); 5278618Sroot bp = bread(ip->i_dev, fsbtodb(fs, bn), 5288618Sroot (int)fs->fs_bsize); 529*9165Ssam if (bp->b_flags&B_ERROR) { 530*9165Ssam brelse(copy); 53124Sbill brelse(bp); 532*9165Ssam return (NULL); 53324Sbill } 53424Sbill bap = bp->b_un.b_daddr; 535*9165Ssam /* 536*9165Ssam * Update pointers before freeing blocks. 537*9165Ssam * If we crash before freeing the blocks 538*9165Ssam * they'll be recovered as missing. 539*9165Ssam */ 540*9165Ssam bcopy((caddr_t)bap, (caddr_t)copy->b_un.b_daddr, 541*9165Ssam (u_int)fs->fs_bsize); 542*9165Ssam bzero((caddr_t)&bap[last + 1], 543*9165Ssam (u_int)(NINDIR(fs) - (last + 1)) * sizeof (daddr_t)); 544*9165Ssam bwrite(bp); 545*9165Ssam bp = copy, bap = bp->b_un.b_daddr; 54624Sbill } 54724Sbill nb = bap[i]; 548*9165Ssam if (nb == 0) 54924Sbill continue; 550*9165Ssam if (doubleindirect) 5517651Ssam #ifdef QUOTA 552*9165Ssam blocksreleased += 5537492Skre #endif 554*9165Ssam indirtrunc(ip, nb, (daddr_t)-1, 0); 555*9165Ssam free(ip, nb, (int)fs->fs_bsize); 5567651Ssam #ifdef QUOTA 557*9165Ssam blocksreleased += nblocks; 5587492Skre #endif 55924Sbill } 560*9165Ssam if (doubleindirect && lastbn >= 0) { 561*9165Ssam last = lastbn % NINDIR(fs); 562*9165Ssam if (bp == NULL) 563*9165Ssam panic("indirtrunc"); 564*9165Ssam nb = bap[i]; 565*9165Ssam if (nb != 0) 566*9165Ssam #ifdef QUOTA 567*9165Ssam blocksreleased += 568*9165Ssam #endif 569*9165Ssam indirtrunc(ip, nb, last, 0); 570*9165Ssam } 5714818Swnj if (bp != NULL) 57224Sbill brelse(bp); 5737651Ssam #ifdef QUOTA 574*9165Ssam return (blocksreleased); 5757492Skre #endif 57624Sbill } 57724Sbill 57824Sbill /* 5797334Skre * remove any inodes in the inode cache belonging to dev 5807334Skre * 5817334Skre * There should not be any active ones, return error if any are found 5827334Skre * (nb: this is a user error, not a system err) 5837334Skre * 5847334Skre * Also, count the references to dev by block devices - this really 5857334Skre * has nothing to do with the object of the procedure, but as we have 5867334Skre * to scan the inode table here anyway, we might as well get the 5877334Skre * extra benefit. 5887334Skre * 5897334Skre * this is called from sumount()/sys3.c when dev is being unmounted 5907334Skre */ 5917651Ssam #ifdef QUOTA 5927504Sroot iflush(dev, iq) 5937492Skre dev_t dev; 5947504Sroot struct inode *iq; 5957492Skre #else 5967334Skre iflush(dev) 5977334Skre dev_t dev; 5987492Skre #endif 5997334Skre { 6007335Skre register struct inode *ip; 6017334Skre register open = 0; 6027334Skre 6037334Skre for (ip = inode; ip < inodeNINODE; ip++) { 6047651Ssam #ifdef QUOTA 6057492Skre if (ip != iq && ip->i_dev == dev) 6067492Skre #else 6077334Skre if (ip->i_dev == dev) 6087492Skre #endif 6097334Skre if (ip->i_count) 6107334Skre return(-1); 6117334Skre else { 6127335Skre remque(ip); 6137334Skre ip->i_forw = ip; 6147334Skre ip->i_back = ip; 6157334Skre /* 6167334Skre * as i_count == 0, the inode was on the free 6177334Skre * list already, just leave it there, it will 6187334Skre * fall off the bottom eventually. We could 6197334Skre * perhaps move it to the head of the free 6207334Skre * list, but as umounts are done so 6217334Skre * infrequently, we would gain very little, 6227334Skre * while making the code bigger. 6237334Skre */ 6247651Ssam #ifdef QUOTA 6257492Skre dqrele(ip->i_dquot); 6267492Skre ip->i_dquot = NODQUOT; 6277492Skre #endif 6287334Skre } 6297334Skre else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK && 6307334Skre ip->i_rdev == dev) 6317334Skre open++; 6327334Skre } 6337334Skre return (open); 6347334Skre } 6357334Skre 6363617Sroot /* 6374818Swnj * Lock an inode. If its already locked, set the WANT bit and sleep. 6383617Sroot */ 6394818Swnj ilock(ip) 6404818Swnj register struct inode *ip; 6413617Sroot { 6423617Sroot 6438452Sroot ILOCK(ip); 6443617Sroot } 6453617Sroot 6463617Sroot /* 6474818Swnj * Unlock an inode. If WANT bit is on, wakeup. 6483617Sroot */ 6497118Smckusick iunlock(ip) 6504818Swnj register struct inode *ip; 6513617Sroot { 6523617Sroot 6538452Sroot IUNLOCK(ip); 6543617Sroot } 655