1*16524Skarels /* lfs_inode.c 6.4 84/05/22 */ 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 17*16524Skarels #define INOHSZ 64 187334Skre #if ((INOHSZ&(INOHSZ-1)) == 0) 197334Skre #define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1)) 207334Skre #else 2110852Ssam #define INOHASH(dev,ino) (((unsigned)((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: 1127334Skre ih = &ihead[INOHASH(dev, ino)]; 1137334Skre for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) 1144818Swnj if (ino == ip->i_number && dev == ip->i_dev) { 1158452Sroot if ((ip->i_flag&ILOCKED) != 0) { 11624Sbill ip->i_flag |= IWANT; 11724Sbill sleep((caddr_t)ip, PINOD); 11824Sbill goto loop; 11924Sbill } 1204818Swnj if ((ip->i_flag&IMOUNT) != 0) { 1216569Smckusic for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 1227334Skre if(mp->m_inodp == ip) { 1237334Skre dev = mp->m_dev; 1247334Skre fs = mp->m_bufp->b_un.b_fs; 1257334Skre ino = ROOTINO; 1267334Skre goto loop; 1277334Skre } 12824Sbill panic("no imt"); 12924Sbill } 1307334Skre if (ip->i_count == 0) { /* ino on free list */ 1317334Skre if (iq = ip->i_freef) 1327334Skre iq->i_freeb = ip->i_freeb; 1337334Skre else 1347334Skre ifreet = ip->i_freeb; 1357334Skre *ip->i_freeb = iq; 1367334Skre ip->i_freef = NULL; 1377334Skre ip->i_freeb = NULL; 1387334Skre } 13924Sbill ip->i_count++; 1408452Sroot ip->i_flag |= ILOCKED; 14124Sbill return(ip); 14224Sbill } 1437334Skre 1447334Skre if ((ip = ifreeh) == NULL) { 1452933Swnj tablefull("inode"); 14624Sbill u.u_error = ENFILE; 14724Sbill return(NULL); 14824Sbill } 1497334Skre if (iq = ip->i_freef) 1507334Skre iq->i_freeb = &ifreeh; 1517334Skre ifreeh = iq; 1527334Skre ip->i_freef = NULL; 1537334Skre ip->i_freeb = NULL; 1547334Skre /* 1557334Skre * Now to take inode off the hash chain it was on 1567334Skre * (initially, or after an iflush, it is on a "hash chain" 1577334Skre * consisting entirely of itself, and pointed to by no-one, 1587334Skre * but that doesn't matter), and put it on the chain for 1597334Skre * its new (ino, dev) pair 1607334Skre */ 1617335Skre remque(ip); 1627335Skre insque(ip, ih); 1637651Ssam #ifdef QUOTA 1647492Skre dqrele(ip->i_dquot); 1657492Skre #endif 16624Sbill ip->i_dev = dev; 1676569Smckusic ip->i_fs = fs; 16824Sbill ip->i_number = ino; 1698452Sroot ip->i_flag = ILOCKED; 17024Sbill ip->i_count++; 1716569Smckusic ip->i_lastr = 0; 1728618Sroot bp = bread(dev, fsbtodb(fs, itod(fs, ino)), (int)fs->fs_bsize); 17324Sbill /* 17424Sbill * Check I/O errors 17524Sbill */ 1764818Swnj if ((bp->b_flags&B_ERROR) != 0) { 17724Sbill brelse(bp); 1787334Skre /* 1797334Skre * the inode doesn't contain anything useful, so it would 1807334Skre * be misleading to leave it on its hash chain. 1817334Skre * 'iput' will take care of putting it back on the free list. 1827334Skre */ 1837335Skre remque(ip); 1847334Skre ip->i_forw = ip; 1857334Skre ip->i_back = ip; 1867334Skre /* 1877334Skre * we also loose its inumber, just in case (as iput 1887334Skre * doesn't do that any more) - but as it isn't on its 1897334Skre * hash chain, I doubt if this is really necessary .. kre 1907334Skre * (probably the two methods are interchangable) 1917334Skre */ 1927334Skre ip->i_number = 0; 1937651Ssam #ifdef QUOTA 1947492Skre ip->i_dquot = NODQUOT; 1957492Skre #endif 19624Sbill iput(ip); 19724Sbill return(NULL); 19824Sbill } 19924Sbill dp = bp->b_un.b_dino; 2006569Smckusic dp += itoo(fs, ino); 2016569Smckusic ip->i_ic = dp->di_ic; 20224Sbill brelse(bp); 2037651Ssam #ifdef QUOTA 2047492Skre if (ip->i_mode == 0) 2057492Skre ip->i_dquot = NODQUOT; 2067492Skre else 2077492Skre ip->i_dquot = inoquota(ip); 2087492Skre #endif 2096569Smckusic return (ip); 21024Sbill } 21124Sbill 21224Sbill /* 21324Sbill * Decrement reference count of 21424Sbill * an inode structure. 21524Sbill * On the last reference, 21624Sbill * write the inode out and if necessary, 21724Sbill * truncate and deallocate the file. 21824Sbill */ 21924Sbill iput(ip) 2204818Swnj register struct inode *ip; 22124Sbill { 2227118Smckusick 2238452Sroot if ((ip->i_flag & ILOCKED) == 0) 2247118Smckusick panic("iput"); 2257118Smckusick iunlock(ip); 2267118Smckusick irele(ip); 2277118Smckusick } 2287118Smckusick 2297118Smckusick irele(ip) 2307118Smckusick register struct inode *ip; 2317118Smckusick { 2326569Smckusic int mode; 23324Sbill 2344818Swnj if (ip->i_count == 1) { 2358452Sroot ip->i_flag |= ILOCKED; 2364818Swnj if (ip->i_nlink <= 0) { 2379165Ssam itrunc(ip, (u_long)0); 2386569Smckusic mode = ip->i_mode; 23924Sbill ip->i_mode = 0; 2407351Skre ip->i_rdev = 0; 24124Sbill ip->i_flag |= IUPD|ICHG; 2426569Smckusic ifree(ip, ip->i_number, mode); 2437651Ssam #ifdef QUOTA 24412645Ssam (void) chkiq(ip->i_dev, ip, ip->i_uid, 0); 2457492Skre dqrele(ip->i_dquot); 2467492Skre ip->i_dquot = NODQUOT; 2477492Skre #endif 24824Sbill } 2498671Sroot IUPDAT(ip, &time, &time, 0); 2507118Smckusick iunlock(ip); 2517334Skre ip->i_flag = 0; 2527334Skre /* 2537334Skre * Put the inode on the end of the free list. 2547334Skre * Possibly in some cases it would be better to 2557334Skre * put the inode at the head of the free list, 2567334Skre * (eg: where i_mode == 0 || i_number == 0) 2577334Skre * but I will think about that later .. kre 2587334Skre * (i_number is rarely 0 - only after an i/o error in iget, 2597334Skre * where i_mode == 0, the inode will probably be wanted 2607334Skre * again soon for an ialloc, so possibly we should keep it) 2617334Skre */ 2627334Skre if (ifreeh) { 2637334Skre *ifreet = ip; 2647334Skre ip->i_freeb = ifreet; 26524Sbill } else { 2667334Skre ifreeh = ip; 2677334Skre ip->i_freeb = &ifreeh; 26824Sbill } 2697334Skre ip->i_freef = NULL; 2707334Skre ifreet = &ip->i_freef; 27116058Skarels } else if (!(ip->i_flag & ILOCKED)) 27216058Skarels ITIMES(ip, &time, &time); 27324Sbill ip->i_count--; 27424Sbill } 27524Sbill 27624Sbill /* 27724Sbill * Check accessed and update flags on 27824Sbill * an inode structure. 27924Sbill * If any is on, update the inode 28024Sbill * with the current time. 2811203Sbill * If waitfor is given, then must insure 2821203Sbill * i/o order so wait for write to complete. 28324Sbill */ 2841203Sbill iupdat(ip, ta, tm, waitfor) 2854818Swnj register struct inode *ip; 2868630Sroot struct timeval *ta, *tm; 2874818Swnj int waitfor; 28824Sbill { 28924Sbill register struct buf *bp; 29024Sbill struct dinode *dp; 2916569Smckusic register struct fs *fp; 29224Sbill 2936569Smckusic fp = ip->i_fs; 29416058Skarels if ((ip->i_flag & (IUPD|IACC|ICHG|IMOD)) != 0) { 2956569Smckusic if (fp->fs_ronly) 29624Sbill return; 2976569Smckusic bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)), 2988618Sroot (int)fp->fs_bsize); 29924Sbill if (bp->b_flags & B_ERROR) { 30024Sbill brelse(bp); 30124Sbill return; 30224Sbill } 3034818Swnj if (ip->i_flag&IACC) 3048630Sroot ip->i_atime = ta->tv_sec; 3054818Swnj if (ip->i_flag&IUPD) 3068630Sroot ip->i_mtime = tm->tv_sec; 3074818Swnj if (ip->i_flag&ICHG) 3088106Sroot ip->i_ctime = time.tv_sec; 30916058Skarels ip->i_flag &= ~(IUPD|IACC|ICHG|IMOD); 3107343Skre dp = bp->b_un.b_dino + itoo(fp, ip->i_number); 3117343Skre dp->di_ic = ip->i_ic; 3121203Sbill if (waitfor) 3131203Sbill bwrite(bp); 3141203Sbill else 3151203Sbill bdwrite(bp); 31624Sbill } 31724Sbill } 31824Sbill 31910736Ssam #define SINGLE 0 /* index of single indirect block */ 32010736Ssam #define DOUBLE 1 /* index of double indirect block */ 32110736Ssam #define TRIPLE 2 /* index of triple indirect block */ 32224Sbill /* 3237702Ssam * Truncate the inode ip to at most 3247702Ssam * length size. Free affected disk 3257702Ssam * blocks -- the blocks of the file 3267702Ssam * are removed in reverse order. 32710736Ssam * 32810736Ssam * NB: triple indirect blocks are untested. 32924Sbill */ 33010736Ssam itrunc(oip, length) 33110736Ssam struct inode *oip; 3329165Ssam u_long length; 33324Sbill { 33424Sbill register i; 3359165Ssam register daddr_t lastblock; 33610736Ssam daddr_t bn, lastiblock[NIADDR]; 3376569Smckusic register struct fs *fs; 33810736Ssam register struct inode *ip; 33910736Ssam struct inode tip; 3409165Ssam long blocksreleased = 0, nblocks; 3419165Ssam long indirtrunc(); 34212645Ssam int level; 3439165Ssam 34413000Ssam if (oip->i_size <= length) { 34513000Ssam oip->i_flag |= ICHG|IUPD; 34613000Ssam iupdat(oip, &time, &time, 1); 3479165Ssam return; 34813000Ssam } 3491203Sbill /* 35010736Ssam * Calculate index into inode's block list of 35110736Ssam * last direct and indirect blocks (if any) 35210736Ssam * which we want to keep. Lastblock is -1 when 35310736Ssam * the file is truncated to 0. 3541203Sbill */ 35510736Ssam fs = oip->i_fs; 3569165Ssam lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1; 35710736Ssam lastiblock[SINGLE] = lastblock - NDADDR; 35810736Ssam lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs); 35910736Ssam lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs); 36012645Ssam nblocks = btodb(fs->fs_bsize); 3616569Smckusic /* 36210736Ssam * Update size of file and block pointers 36310736Ssam * on disk before we start freeing blocks. 36410736Ssam * If we crash before free'ing blocks below, 36510736Ssam * the blocks will be returned to the free list. 36610736Ssam * lastiblock values are also normalized to -1 36710736Ssam * for calls to indirtrunc below. 36810736Ssam * (? fsck doesn't check validity of pointers in indirect blocks) 3696569Smckusic */ 37010736Ssam tip = *oip; 37110736Ssam for (level = TRIPLE; level >= SINGLE; level--) 37210736Ssam if (lastiblock[level] < 0) { 37310736Ssam oip->i_ib[level] = 0; 37410736Ssam lastiblock[level] = -1; 3759165Ssam } 37610736Ssam for (i = NDADDR - 1; i > lastblock; i--) 37710736Ssam oip->i_db[i] = 0; 37810736Ssam oip->i_size = length; 37910736Ssam oip->i_flag |= ICHG|IUPD; 38010736Ssam iupdat(oip, &time, &time, 1); 38110736Ssam ip = &tip; 38210736Ssam 3836569Smckusic /* 38410736Ssam * Indirect blocks first. 3856569Smckusic */ 38610736Ssam for (level = TRIPLE; level >= SINGLE; level--) { 38710736Ssam bn = ip->i_ib[level]; 3889165Ssam if (bn != 0) { 38910736Ssam blocksreleased += 39012645Ssam indirtrunc(ip, bn, lastiblock[level], level); 39110736Ssam if (lastiblock[level] < 0) { 39210736Ssam ip->i_ib[level] = 0; 39310736Ssam free(ip, bn, (off_t)fs->fs_bsize); 39410736Ssam blocksreleased += nblocks; 39510736Ssam } 39610736Ssam } 39710736Ssam if (lastiblock[level] >= 0) 39810736Ssam goto done; 3999165Ssam } 40010736Ssam 4016569Smckusic /* 40210736Ssam * All whole direct blocks or frags. 4036569Smckusic */ 4049165Ssam for (i = NDADDR - 1; i > lastblock; i--) { 4059165Ssam register int size; 4069165Ssam 4076569Smckusic bn = ip->i_db[i]; 4089165Ssam if (bn == 0) 40924Sbill continue; 4109165Ssam ip->i_db[i] = 0; 4119165Ssam size = (off_t)blksize(fs, ip, i); 4129165Ssam free(ip, bn, size); 41312645Ssam blocksreleased += btodb(size); 41424Sbill } 41510736Ssam if (lastblock < 0) 41610736Ssam goto done; 41710736Ssam 4181203Sbill /* 4199165Ssam * Finally, look for a change in size of the 4209165Ssam * last direct block; release any frags. 4211203Sbill */ 42210736Ssam bn = ip->i_db[lastblock]; 42310736Ssam if (bn != 0) { 42410736Ssam int oldspace, newspace; 42510736Ssam 4269165Ssam /* 4279165Ssam * Calculate amount of space we're giving 4289165Ssam * back as old block size minus new block size. 4299165Ssam */ 43010736Ssam oldspace = blksize(fs, ip, lastblock); 4319165Ssam ip->i_size = length; 43210736Ssam newspace = blksize(fs, ip, lastblock); 43310736Ssam if (newspace == 0) 43410736Ssam panic("itrunc: newspace"); 43510736Ssam if (oldspace - newspace > 0) { 4369165Ssam /* 4379165Ssam * Block number of space to be free'd is 4389165Ssam * the old block # plus the number of frags 4399165Ssam * required for the storage we're keeping. 4409165Ssam */ 44110736Ssam bn += numfrags(fs, newspace); 44210736Ssam free(ip, bn, oldspace - newspace); 44312645Ssam blocksreleased += btodb(oldspace - newspace); 4449165Ssam } 4459165Ssam } 4469165Ssam done: 44710736Ssam /* BEGIN PARANOIA */ 44810736Ssam for (level = SINGLE; level <= TRIPLE; level++) 44910736Ssam if (ip->i_ib[level] != oip->i_ib[level]) 45010736Ssam panic("itrunc1"); 45110736Ssam for (i = 0; i < NDADDR; i++) 45210736Ssam if (ip->i_db[i] != oip->i_db[i]) 45310736Ssam panic("itrunc2"); 45410736Ssam /* END PARANOIA */ 45512645Ssam oip->i_blocks -= blocksreleased; 45612645Ssam if (oip->i_blocks < 0) /* sanity */ 45712645Ssam oip->i_blocks = 0; 45812645Ssam oip->i_flag |= ICHG; 4599165Ssam #ifdef QUOTA 46012645Ssam (void) chkdq(oip, -blocksreleased, 0); 4619165Ssam #endif 46224Sbill } 46324Sbill 4649165Ssam /* 4659165Ssam * Release blocks associated with the inode ip and 4669165Ssam * stored in the indirect block bn. Blocks are free'd 4679165Ssam * in LIFO order up to (but not including) lastbn. If 46810736Ssam * level is greater than SINGLE, the block is an indirect 46910736Ssam * block and recursive calls to indirtrunc must be used to 47010736Ssam * cleanse other indirect blocks. 47110736Ssam * 47210736Ssam * NB: triple indirect blocks are untested. 4739165Ssam */ 4747492Skre long 47510736Ssam indirtrunc(ip, bn, lastbn, level) 4766569Smckusic register struct inode *ip; 4779165Ssam daddr_t bn, lastbn; 47810736Ssam int level; 47924Sbill { 4809165Ssam register int i; 48110736Ssam struct buf *bp, *copy; 48224Sbill register daddr_t *bap; 48310736Ssam register struct fs *fs = ip->i_fs; 4849165Ssam daddr_t nb, last; 48510736Ssam long factor; 4869165Ssam int blocksreleased = 0, nblocks; 48724Sbill 48810736Ssam /* 48910736Ssam * Calculate index in current block of last 49010736Ssam * block to be kept. -1 indicates the entire 49110736Ssam * block so we need not calculate the index. 49210736Ssam */ 49310736Ssam factor = 1; 49410736Ssam for (i = SINGLE; i < level; i++) 49510736Ssam factor *= NINDIR(fs); 4969165Ssam last = lastbn; 49710736Ssam if (lastbn > 0) 49810736Ssam last /= factor; 49912645Ssam nblocks = btodb(fs->fs_bsize); 50010736Ssam /* 50110736Ssam * Get buffer of block pointers, zero those 50210736Ssam * entries corresponding to blocks to be free'd, 50310736Ssam * and update on disk copy first. 50410736Ssam */ 50510736Ssam copy = geteblk((int)fs->fs_bsize); 50610736Ssam bp = bread(ip->i_dev, fsbtodb(fs, bn), (int)fs->fs_bsize); 50710736Ssam if (bp->b_flags&B_ERROR) { 50810736Ssam brelse(copy); 50910736Ssam brelse(bp); 51010736Ssam return (0); 51110736Ssam } 51210736Ssam bap = bp->b_un.b_daddr; 51310736Ssam bcopy((caddr_t)bap, (caddr_t)copy->b_un.b_daddr, (u_int)fs->fs_bsize); 51410736Ssam bzero((caddr_t)&bap[last + 1], 51510736Ssam (u_int)(NINDIR(fs) - (last + 1)) * sizeof (daddr_t)); 51610736Ssam bwrite(bp); 51710736Ssam bp = copy, bap = bp->b_un.b_daddr; 51810736Ssam 51910736Ssam /* 52010736Ssam * Recursively free totally unused blocks. 52110736Ssam */ 5229165Ssam for (i = NINDIR(fs) - 1; i > last; i--) { 52324Sbill nb = bap[i]; 5249165Ssam if (nb == 0) 52524Sbill continue; 52610736Ssam if (level > SINGLE) 5279165Ssam blocksreleased += 52812645Ssam indirtrunc(ip, nb, (daddr_t)-1, level - 1); 5299165Ssam free(ip, nb, (int)fs->fs_bsize); 5309165Ssam blocksreleased += nblocks; 53124Sbill } 53210736Ssam 53310736Ssam /* 53410736Ssam * Recursively free last partial block. 53510736Ssam */ 53610736Ssam if (level > SINGLE && lastbn >= 0) { 53710736Ssam last = lastbn % factor; 5389165Ssam nb = bap[i]; 5399165Ssam if (nb != 0) 54012645Ssam blocksreleased += indirtrunc(ip, nb, last, level - 1); 5419165Ssam } 54210736Ssam brelse(bp); 5439165Ssam return (blocksreleased); 54424Sbill } 54524Sbill 54624Sbill /* 5477334Skre * remove any inodes in the inode cache belonging to dev 5487334Skre * 5497334Skre * There should not be any active ones, return error if any are found 5507334Skre * (nb: this is a user error, not a system err) 5517334Skre * 5527334Skre * Also, count the references to dev by block devices - this really 5537334Skre * has nothing to do with the object of the procedure, but as we have 5547334Skre * to scan the inode table here anyway, we might as well get the 5557334Skre * extra benefit. 5567334Skre * 5577334Skre * this is called from sumount()/sys3.c when dev is being unmounted 5587334Skre */ 5597651Ssam #ifdef QUOTA 5607504Sroot iflush(dev, iq) 5617492Skre dev_t dev; 5627504Sroot struct inode *iq; 5637492Skre #else 5647334Skre iflush(dev) 5657334Skre dev_t dev; 5667492Skre #endif 5677334Skre { 5687335Skre register struct inode *ip; 5697334Skre register open = 0; 5707334Skre 5717334Skre for (ip = inode; ip < inodeNINODE; ip++) { 5727651Ssam #ifdef QUOTA 5737492Skre if (ip != iq && ip->i_dev == dev) 5747492Skre #else 5757334Skre if (ip->i_dev == dev) 5767492Skre #endif 5777334Skre if (ip->i_count) 5787334Skre return(-1); 5797334Skre else { 5807335Skre remque(ip); 5817334Skre ip->i_forw = ip; 5827334Skre ip->i_back = ip; 5837334Skre /* 5847334Skre * as i_count == 0, the inode was on the free 5857334Skre * list already, just leave it there, it will 5867334Skre * fall off the bottom eventually. We could 5877334Skre * perhaps move it to the head of the free 5887334Skre * list, but as umounts are done so 5897334Skre * infrequently, we would gain very little, 5907334Skre * while making the code bigger. 5917334Skre */ 5927651Ssam #ifdef QUOTA 5937492Skre dqrele(ip->i_dquot); 5947492Skre ip->i_dquot = NODQUOT; 5957492Skre #endif 5967334Skre } 5977334Skre else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK && 5987334Skre ip->i_rdev == dev) 5997334Skre open++; 6007334Skre } 6017334Skre return (open); 6027334Skre } 6037334Skre 6043617Sroot /* 6054818Swnj * Lock an inode. If its already locked, set the WANT bit and sleep. 6063617Sroot */ 6074818Swnj ilock(ip) 6084818Swnj register struct inode *ip; 6093617Sroot { 6103617Sroot 6118452Sroot ILOCK(ip); 6123617Sroot } 6133617Sroot 6143617Sroot /* 6154818Swnj * Unlock an inode. If WANT bit is on, wakeup. 6163617Sroot */ 6177118Smckusick iunlock(ip) 6184818Swnj register struct inode *ip; 6193617Sroot { 6203617Sroot 6218452Sroot IUNLOCK(ip); 6223617Sroot } 623