1*7335Skre /* lfs_inode.c 4.14 82/06/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" 1324Sbill 1424Sbill #define INOHSZ 63 157334Skre #if ((INOHSZ&(INOHSZ-1)) == 0) 167334Skre #define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1)) 177334Skre #else 1824Sbill #define INOHASH(dev,ino) (((dev)+(ino))%INOHSZ) 197334Skre #endif 2024Sbill 217334Skre union ihead { /* inode LRU cache, Chris Maltby */ 227334Skre union ihead *ih_head[2]; 237334Skre struct inode *ih_chain[2]; 247334Skre } ihead[INOHSZ]; 257334Skre 267334Skre struct inode *ifreeh, **ifreet; 277334Skre 2824Sbill /* 2924Sbill * Initialize hash links for inodes 3024Sbill * and build inode free list. 3124Sbill */ 3224Sbill ihinit() 3324Sbill { 3424Sbill register int i; 352737Swnj register struct inode *ip = inode; 367334Skre register union ihead *ih = ihead; 3724Sbill 387334Skre for (i = INOHSZ; --i >= 0; ih++) { 397334Skre ih->ih_head[0] = ih; 407334Skre ih->ih_head[1] = ih; 417334Skre } 427334Skre ifreeh = ip; 437334Skre ifreet = &ip->i_freef; 447334Skre ip->i_freeb = &ifreeh; 457334Skre ip->i_forw = ip; 467334Skre ip->i_back = ip; 477334Skre for (i = ninode; --i > 0; ) { 487334Skre ++ip; 497334Skre ip->i_forw = ip; 507334Skre ip->i_back = ip; 517334Skre *ifreet = ip; 527334Skre ip->i_freeb = ifreet; 537334Skre ifreet = &ip->i_freef; 547334Skre } 557334Skre ip->i_freef = NULL; 5624Sbill } 5724Sbill 587334Skre #ifdef notdef 5924Sbill /* 607334Skre * Find an inode if it is incore. 617334Skre * This is the equivalent, for inodes, 627334Skre * of ``incore'' in bio.c or ``pfind'' in subr.c. 637334Skre */ 647334Skre struct inode * 657334Skre ifind(dev, ino) 667334Skre dev_t dev; 677334Skre ino_t ino; 687334Skre { 697334Skre register struct inode *ip; 707334Skre register union ihead *ih; 717334Skre 727334Skre ih = &ihead[INOHASH(dev, ino)]; 737334Skre for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) 747334Skre if (ino==ip->i_number && dev==ip->i_dev) 757334Skre return (ip); 767334Skre return ((struct inode *)0); 777334Skre } 787334Skre #endif notdef 797334Skre 807334Skre /* 8124Sbill * Look up an inode by device,inumber. 8224Sbill * If it is in core (in the inode structure), 8324Sbill * honor the locking protocol. 8424Sbill * If it is not in core, read it in from the 8524Sbill * specified device. 8624Sbill * If the inode is mounted on, perform 8724Sbill * the indicated indirection. 8824Sbill * In all cases, a pointer to a locked 8924Sbill * inode structure is returned. 9024Sbill * 9124Sbill * panic: no imt -- if the mounted file 9224Sbill * system is not in the mount table. 9324Sbill * "cannot happen" 9424Sbill */ 9524Sbill struct inode * 966569Smckusic iget(dev, fs, ino) 974818Swnj dev_t dev; 986569Smckusic register struct fs *fs; 994818Swnj ino_t ino; 10024Sbill { 101*7335Skre register struct inode *ip; 102*7335Skre register union ihead *ih; 10324Sbill register struct mount *mp; 10424Sbill register struct buf *bp; 10524Sbill register struct dinode *dp; 1067334Skre register struct inode *iq; 10724Sbill 10824Sbill loop: 1096569Smckusic if (getfs(dev) != fs) 1106569Smckusic panic("iget: bad fs"); 1117334Skre ih = &ihead[INOHASH(dev, ino)]; 1127334Skre for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) 1134818Swnj if (ino == ip->i_number && dev == ip->i_dev) { 1144818Swnj if ((ip->i_flag&ILOCK) != 0) { 11524Sbill ip->i_flag |= IWANT; 11624Sbill sleep((caddr_t)ip, PINOD); 11724Sbill goto loop; 11824Sbill } 1194818Swnj if ((ip->i_flag&IMOUNT) != 0) { 1206569Smckusic for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 1217334Skre if(mp->m_inodp == ip) { 1227334Skre dev = mp->m_dev; 1237334Skre fs = mp->m_bufp->b_un.b_fs; 1247334Skre ino = ROOTINO; 1257334Skre goto loop; 1267334Skre } 12724Sbill panic("no imt"); 12824Sbill } 1297334Skre if (ip->i_count == 0) { /* ino on free list */ 1307334Skre if (iq = ip->i_freef) 1317334Skre iq->i_freeb = ip->i_freeb; 1327334Skre else 1337334Skre ifreet = ip->i_freeb; 1347334Skre *ip->i_freeb = iq; 1357334Skre ip->i_freef = NULL; 1367334Skre ip->i_freeb = NULL; 1377334Skre } 13824Sbill ip->i_count++; 13924Sbill ip->i_flag |= ILOCK; 14024Sbill return(ip); 14124Sbill } 1427334Skre 1437334Skre if ((ip = ifreeh) == NULL) { 1442933Swnj tablefull("inode"); 14524Sbill u.u_error = ENFILE; 14624Sbill return(NULL); 14724Sbill } 1487334Skre if (iq = ip->i_freef) 1497334Skre iq->i_freeb = &ifreeh; 1507334Skre ifreeh = iq; 1517334Skre ip->i_freef = NULL; 1527334Skre ip->i_freeb = NULL; 1537334Skre /* 1547334Skre * Now to take inode off the hash chain it was on 1557334Skre * (initially, or after an iflush, it is on a "hash chain" 1567334Skre * consisting entirely of itself, and pointed to by no-one, 1577334Skre * but that doesn't matter), and put it on the chain for 1587334Skre * its new (ino, dev) pair 1597334Skre */ 160*7335Skre remque(ip); 161*7335Skre insque(ip, ih); 16224Sbill ip->i_dev = dev; 1636569Smckusic ip->i_fs = fs; 16424Sbill ip->i_number = ino; 16524Sbill ip->i_flag = ILOCK; 16624Sbill ip->i_count++; 1676569Smckusic ip->i_lastr = 0; 1686569Smckusic bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize); 16924Sbill /* 17024Sbill * Check I/O errors 17124Sbill */ 1724818Swnj if ((bp->b_flags&B_ERROR) != 0) { 17324Sbill brelse(bp); 1747334Skre /* 1757334Skre * the inode doesn't contain anything useful, so it would 1767334Skre * be misleading to leave it on its hash chain. 1777334Skre * 'iput' will take care of putting it back on the free list. 1787334Skre */ 179*7335Skre remque(ip); 1807334Skre ip->i_forw = ip; 1817334Skre ip->i_back = ip; 1827334Skre /* 1837334Skre * we also loose its inumber, just in case (as iput 1847334Skre * doesn't do that any more) - but as it isn't on its 1857334Skre * hash chain, I doubt if this is really necessary .. kre 1867334Skre * (probably the two methods are interchangable) 1877334Skre */ 1887334Skre ip->i_number = 0; 18924Sbill iput(ip); 19024Sbill return(NULL); 19124Sbill } 19224Sbill dp = bp->b_un.b_dino; 1936569Smckusic dp += itoo(fs, ino); 1946569Smckusic ip->i_ic = dp->di_ic; 19524Sbill brelse(bp); 1966569Smckusic return (ip); 19724Sbill } 19824Sbill 19924Sbill /* 20024Sbill * Decrement reference count of 20124Sbill * an inode structure. 20224Sbill * On the last reference, 20324Sbill * write the inode out and if necessary, 20424Sbill * truncate and deallocate the file. 20524Sbill */ 20624Sbill iput(ip) 2074818Swnj register struct inode *ip; 20824Sbill { 2097118Smckusick 2107118Smckusick if ((ip->i_flag & ILOCK) == 0) 2117118Smckusick panic("iput"); 2127118Smckusick iunlock(ip); 2137118Smckusick irele(ip); 2147118Smckusick } 2157118Smckusick 2167118Smckusick irele(ip) 2177118Smckusick register struct inode *ip; 2187118Smckusick { 21924Sbill register int i, x; 22024Sbill register struct inode *jp; 2216569Smckusic int mode; 22224Sbill 2234818Swnj if (ip->i_count == 1) { 22424Sbill ip->i_flag |= ILOCK; 2254818Swnj if (ip->i_nlink <= 0) { 22624Sbill itrunc(ip); 2276569Smckusic mode = ip->i_mode; 22824Sbill ip->i_mode = 0; 22924Sbill ip->i_flag |= IUPD|ICHG; 2306569Smckusic ifree(ip, ip->i_number, mode); 23124Sbill } 2321203Sbill IUPDAT(ip, &time, &time, 0); 2337118Smckusick iunlock(ip); 2347334Skre ip->i_flag = 0; 2357334Skre /* 2367334Skre * Put the inode on the end of the free list. 2377334Skre * Possibly in some cases it would be better to 2387334Skre * put the inode at the head of the free list, 2397334Skre * (eg: where i_mode == 0 || i_number == 0) 2407334Skre * but I will think about that later .. kre 2417334Skre * (i_number is rarely 0 - only after an i/o error in iget, 2427334Skre * where i_mode == 0, the inode will probably be wanted 2437334Skre * again soon for an ialloc, so possibly we should keep it) 2447334Skre */ 2457334Skre if (ifreeh) { 2467334Skre *ifreet = ip; 2477334Skre ip->i_freeb = ifreet; 24824Sbill } else { 2497334Skre ifreeh = ip; 2507334Skre ip->i_freeb = &ifreeh; 25124Sbill } 2527334Skre ip->i_freef = NULL; 2537334Skre ifreet = &ip->i_freef; 2547118Smckusick } 25524Sbill ip->i_count--; 25624Sbill } 25724Sbill 25824Sbill /* 25924Sbill * Check accessed and update flags on 26024Sbill * an inode structure. 26124Sbill * If any is on, update the inode 26224Sbill * with the current time. 2631203Sbill * If waitfor is given, then must insure 2641203Sbill * i/o order so wait for write to complete. 26524Sbill */ 2661203Sbill iupdat(ip, ta, tm, waitfor) 2674818Swnj register struct inode *ip; 2684818Swnj time_t *ta, *tm; 2694818Swnj int waitfor; 27024Sbill { 27124Sbill register struct buf *bp; 27224Sbill struct dinode *dp; 2736569Smckusic register struct fs *fp; 27424Sbill 2756569Smckusic fp = ip->i_fs; 2766569Smckusic if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) { 2776569Smckusic if (fp->fs_ronly) 27824Sbill return; 2796569Smckusic bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)), 2806569Smckusic fp->fs_bsize); 28124Sbill if (bp->b_flags & B_ERROR) { 28224Sbill brelse(bp); 28324Sbill return; 28424Sbill } 2854818Swnj if (ip->i_flag&IACC) 2866569Smckusic ip->i_atime = *ta; 2874818Swnj if (ip->i_flag&IUPD) 2886569Smckusic ip->i_mtime = *tm; 2894818Swnj if (ip->i_flag&ICHG) 2906569Smckusic ip->i_ctime = time; 29124Sbill ip->i_flag &= ~(IUPD|IACC|ICHG); 2921203Sbill if (waitfor) 2931203Sbill bwrite(bp); 2941203Sbill else 2951203Sbill bdwrite(bp); 29624Sbill } 29724Sbill } 29824Sbill 29924Sbill /* 30024Sbill * Free all the disk blocks associated 30124Sbill * with the specified inode structure. 30224Sbill * The blocks of the file are removed 30324Sbill * in reverse order. This FILO 30424Sbill * algorithm will tend to maintain 30524Sbill * a contiguous free list much longer 30624Sbill * than FIFO. 30724Sbill */ 30824Sbill itrunc(ip) 3094818Swnj register struct inode *ip; 31024Sbill { 31124Sbill register i; 31224Sbill dev_t dev; 31324Sbill daddr_t bn; 3141203Sbill struct inode itmp; 3156569Smckusic register struct fs *fs; 31624Sbill 31724Sbill i = ip->i_mode & IFMT; 3186569Smckusic if (i != IFREG && i != IFDIR && i != IFLNK) 31924Sbill return; 3201203Sbill /* 3211203Sbill * Clean inode on disk before freeing blocks 3221203Sbill * to insure no duplicates if system crashes. 3231203Sbill */ 3241203Sbill itmp = *ip; 3251203Sbill itmp.i_size = 0; 3266569Smckusic for (i = 0; i < NDADDR; i++) 3276569Smckusic itmp.i_db[i] = 0; 3286569Smckusic for (i = 0; i < NIADDR; i++) 3296569Smckusic itmp.i_ib[i] = 0; 3301203Sbill itmp.i_flag |= ICHG|IUPD; 3311203Sbill iupdat(&itmp, &time, &time, 1); 3321203Sbill ip->i_flag &= ~(IUPD|IACC|ICHG); 3331203Sbill 3341203Sbill /* 3351203Sbill * Now return blocks to free list... if machine 3361203Sbill * crashes, they will be harmless MISSING blocks. 3371203Sbill */ 33824Sbill dev = ip->i_dev; 3396569Smckusic fs = ip->i_fs; 3406569Smckusic /* 3416569Smckusic * release double indirect block first 3426569Smckusic */ 3436569Smckusic bn = ip->i_ib[NIADDR-1]; 3446569Smckusic if (bn != (daddr_t)0) { 3456569Smckusic ip->i_ib[NIADDR - 1] = (daddr_t)0; 3466569Smckusic tloop(ip, bn, 1); 3476569Smckusic } 3486569Smckusic /* 3496569Smckusic * release single indirect blocks second 3506569Smckusic */ 3516569Smckusic for (i = NIADDR - 2; i >= 0; i--) { 3526569Smckusic bn = ip->i_ib[i]; 3536569Smckusic if (bn != (daddr_t)0) { 3546569Smckusic ip->i_ib[i] = (daddr_t)0; 3556569Smckusic tloop(ip, bn, 0); 3566569Smckusic } 3576569Smckusic } 3586569Smckusic /* 3596569Smckusic * finally release direct blocks 3606569Smckusic */ 3616569Smckusic for (i = NDADDR - 1; i>=0; i--) { 3626569Smckusic bn = ip->i_db[i]; 3634818Swnj if (bn == (daddr_t)0) 36424Sbill continue; 3656569Smckusic ip->i_db[i] = (daddr_t)0; 3666569Smckusic fre(ip, bn, (off_t)blksize(fs, ip, i)); 36724Sbill } 36824Sbill ip->i_size = 0; 3691203Sbill /* 3701203Sbill * Inode was written and flags updated above. 3711203Sbill * No need to modify flags here. 3721203Sbill */ 37324Sbill } 37424Sbill 3756569Smckusic tloop(ip, bn, indflg) 3766569Smckusic register struct inode *ip; 3776569Smckusic daddr_t bn; 3786569Smckusic int indflg; 37924Sbill { 38024Sbill register i; 38124Sbill register struct buf *bp; 38224Sbill register daddr_t *bap; 3836569Smckusic register struct fs *fs; 38424Sbill daddr_t nb; 38524Sbill 38624Sbill bp = NULL; 3876569Smckusic fs = ip->i_fs; 3886569Smckusic for (i = NINDIR(fs) - 1; i >= 0; i--) { 3894818Swnj if (bp == NULL) { 3906569Smckusic bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize); 39124Sbill if (bp->b_flags & B_ERROR) { 39224Sbill brelse(bp); 39324Sbill return; 39424Sbill } 39524Sbill bap = bp->b_un.b_daddr; 39624Sbill } 39724Sbill nb = bap[i]; 3984818Swnj if (nb == (daddr_t)0) 39924Sbill continue; 4006569Smckusic if (indflg) 4016569Smckusic tloop(ip, nb, 0); 4026569Smckusic else 4036569Smckusic fre(ip, nb, fs->fs_bsize); 40424Sbill } 4054818Swnj if (bp != NULL) 40624Sbill brelse(bp); 4076569Smckusic fre(ip, bn, fs->fs_bsize); 40824Sbill } 40924Sbill 41024Sbill /* 41124Sbill * Make a new file. 41224Sbill */ 41324Sbill struct inode * 41424Sbill maknode(mode) 4156569Smckusic int mode; 41624Sbill { 41724Sbill register struct inode *ip; 4186569Smckusic ino_t ipref; 41924Sbill 4206569Smckusic if ((mode & IFMT) == IFDIR) 4216569Smckusic ipref = dirpref(u.u_pdir->i_fs); 4226569Smckusic else 4236569Smckusic ipref = u.u_pdir->i_number; 4246569Smckusic ip = ialloc(u.u_pdir, ipref, mode); 4254818Swnj if (ip == NULL) { 42624Sbill iput(u.u_pdir); 42724Sbill return(NULL); 42824Sbill } 42924Sbill ip->i_flag |= IACC|IUPD|ICHG; 4306569Smckusic if ((mode & IFMT) == 0) 43124Sbill mode |= IFREG; 43224Sbill ip->i_mode = mode & ~u.u_cmask; 43324Sbill ip->i_nlink = 1; 43424Sbill ip->i_uid = u.u_uid; 4355855Swnj ip->i_gid = u.u_pdir->i_gid; 4361203Sbill 4371203Sbill /* 4381203Sbill * Make sure inode goes to disk before directory entry. 4391203Sbill */ 4401203Sbill iupdat(ip, &time, &time, 1); 44124Sbill wdir(ip); 4426569Smckusic if (u.u_error) { 4436569Smckusic /* 4446569Smckusic * write error occurred trying to update directory 4456569Smckusic * so must deallocate the inode 4466569Smckusic */ 4476569Smckusic ip->i_nlink = 0; 4486569Smckusic ip->i_flag |= ICHG; 4496569Smckusic iput(ip); 4506569Smckusic return(NULL); 4516569Smckusic } 45224Sbill return(ip); 45324Sbill } 45424Sbill 45524Sbill /* 45624Sbill * Write a directory entry with 45724Sbill * parameters left as side effects 45824Sbill * to a call to namei. 45924Sbill */ 46024Sbill wdir(ip) 4614818Swnj struct inode *ip; 46224Sbill { 4636569Smckusic register struct direct *dp, *ndp; 4646569Smckusic struct fs *fs; 4656569Smckusic struct buf *bp; 4666569Smckusic int lbn, bn, base; 4676569Smckusic int loc, dsize, spccnt, newsize; 4686569Smckusic char *dirbuf; 46924Sbill 47024Sbill u.u_dent.d_ino = ip->i_number; 47124Sbill u.u_segflg = 1; 4726569Smckusic newsize = DIRSIZ(&u.u_dent); 4736569Smckusic /* 4746569Smckusic * if u.u_count == 0, a new directory block must be allocated. 4756569Smckusic */ 4766569Smckusic if (u.u_count == 0) { 4776569Smckusic u.u_dent.d_reclen = DIRBLKSIZ; 4786569Smckusic u.u_count = newsize; 4796569Smckusic u.u_base = (caddr_t)&u.u_dent; 4806569Smckusic writei(u.u_pdir); 4816569Smckusic iput(u.u_pdir); 4826569Smckusic return; 4836569Smckusic } 4846569Smckusic /* 4856569Smckusic * must read in an existing directory block 4866569Smckusic * to prepare to place the new entry into it. 4876569Smckusic */ 4886569Smckusic fs = u.u_pdir->i_fs; 4896569Smckusic lbn = lblkno(fs, u.u_offset); 4906569Smckusic base = blkoff(fs, u.u_offset); 4916569Smckusic bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count)); 4926569Smckusic if (u.u_offset + u.u_count > u.u_pdir->i_size) 4936569Smckusic u.u_pdir->i_size = u.u_offset + u.u_count; 4946569Smckusic bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn)); 4956569Smckusic if (bp->b_flags & B_ERROR) { 4966569Smckusic brelse(bp); 4976569Smckusic return; 4986569Smckusic } 4996569Smckusic dirbuf = bp->b_un.b_addr + base; 5006569Smckusic dp = (struct direct *)dirbuf; 5016569Smckusic dsize = DIRSIZ(dp); 5026569Smckusic spccnt = dp->d_reclen - dsize; 5036569Smckusic /* 5046569Smckusic * if there is insufficient room to make an entry at this point 5056569Smckusic * namei insures that compacting from u.u_offset for u.u_count 5066569Smckusic * bytes will provide the necessary space. 5076569Smckusic */ 5086569Smckusic for (loc = dp->d_reclen; loc < u.u_count; ) { 5096569Smckusic ndp = (struct direct *)(dirbuf + loc); 5106569Smckusic if (dp->d_ino == 0) { 5116569Smckusic spccnt += dsize; 5126569Smckusic } else { 5136569Smckusic dp->d_reclen = dsize; 5146569Smckusic dp = (struct direct *)((char *)dp + dsize); 5156569Smckusic } 5166569Smckusic dsize = DIRSIZ(ndp); 5176569Smckusic spccnt += ndp->d_reclen - dsize; 5186569Smckusic loc += ndp->d_reclen; 5196569Smckusic bcopy(ndp, dp, dsize); 5206569Smckusic } 5216569Smckusic /* 5226569Smckusic * Update the pointer fields in the previous entry (if any), 5236569Smckusic * copy in the new entry, and write out the block. 5246569Smckusic */ 5256569Smckusic if (dp->d_ino == 0) { 5266569Smckusic if (spccnt + dsize < newsize) 5276569Smckusic panic("wdir: compact failed"); 5286569Smckusic u.u_dent.d_reclen = spccnt + dsize; 5296569Smckusic } else { 5306569Smckusic if (spccnt < newsize) 5316569Smckusic panic("wdir: compact failed"); 5326569Smckusic u.u_dent.d_reclen = spccnt; 5336569Smckusic dp->d_reclen = dsize; 5346569Smckusic dp = (struct direct *)((char *)dp + dsize); 5356569Smckusic } 5366569Smckusic bcopy(&u.u_dent, dp, newsize); 5376569Smckusic bwrite(bp); 5386569Smckusic u.u_pdir->i_flag |= IUPD|ICHG; 53924Sbill iput(u.u_pdir); 54024Sbill } 5413617Sroot 5427334Skre /* 5437334Skre * remove any inodes in the inode cache belonging to dev 5447334Skre * 5457334Skre * There should not be any active ones, return error if any are found 5467334Skre * (nb: this is a user error, not a system err) 5477334Skre * 5487334Skre * Also, count the references to dev by block devices - this really 5497334Skre * has nothing to do with the object of the procedure, but as we have 5507334Skre * to scan the inode table here anyway, we might as well get the 5517334Skre * extra benefit. 5527334Skre * 5537334Skre * this is called from sumount()/sys3.c when dev is being unmounted 5547334Skre */ 5557334Skre iflush(dev) 5567334Skre dev_t dev; 5577334Skre { 558*7335Skre register struct inode *ip; 5597334Skre register open = 0; 5607334Skre 5617334Skre for (ip = inode; ip < inodeNINODE; ip++) { 5627334Skre if (ip->i_dev == dev) 5637334Skre if (ip->i_count) 5647334Skre return(-1); 5657334Skre else { 566*7335Skre remque(ip); 5677334Skre ip->i_forw = ip; 5687334Skre ip->i_back = ip; 5697334Skre /* 5707334Skre * as i_count == 0, the inode was on the free 5717334Skre * list already, just leave it there, it will 5727334Skre * fall off the bottom eventually. We could 5737334Skre * perhaps move it to the head of the free 5747334Skre * list, but as umounts are done so 5757334Skre * infrequently, we would gain very little, 5767334Skre * while making the code bigger. 5777334Skre */ 5787334Skre } 5797334Skre else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK && 5807334Skre ip->i_rdev == dev) 5817334Skre open++; 5827334Skre } 5837334Skre return (open); 5847334Skre } 5857334Skre 5864818Swnj #ifdef ilock 5874818Swnj #undef ilock 5883617Sroot #endif 5897118Smckusick #ifdef iunlock 5907118Smckusick #undef iunlock 5913617Sroot #endif 5923617Sroot /* 5934818Swnj * Lock an inode. If its already locked, set the WANT bit and sleep. 5943617Sroot */ 5954818Swnj ilock(ip) 5964818Swnj register struct inode *ip; 5973617Sroot { 5983617Sroot 5994818Swnj while (ip->i_flag&ILOCK) { 6003617Sroot ip->i_flag |= IWANT; 6013617Sroot sleep((caddr_t)ip, PINOD); 6023617Sroot } 6033617Sroot ip->i_flag |= ILOCK; 6043617Sroot } 6053617Sroot 6063617Sroot /* 6074818Swnj * Unlock an inode. If WANT bit is on, wakeup. 6083617Sroot */ 6097118Smckusick iunlock(ip) 6104818Swnj register struct inode *ip; 6113617Sroot { 6123617Sroot 6133617Sroot ip->i_flag &= ~ILOCK; 6144818Swnj if (ip->i_flag&IWANT) { 6153617Sroot ip->i_flag &= ~IWANT; 6163617Sroot wakeup((caddr_t)ip); 6173617Sroot } 6183617Sroot } 619