4.2 distribution
[unix-history] / usr / src / sys / ufs / lfs / lfs_inode.c
CommitLineData
b11be056 1/* lfs_inode.c 6.1 83/07/29 */
5d5124a1
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/mount.h"
6#include "../h/dir.h"
7#include "../h/user.h"
8#include "../h/inode.h"
6459ebe0 9#include "../h/fs.h"
5d5124a1
BJ
10#include "../h/conf.h"
11#include "../h/buf.h"
b4567e9c 12#ifdef QUOTA
4147b3f6
BJ
13#include "../h/quota.h"
14#endif
3e63ef5b 15#include "../h/kernel.h"
5d5124a1
BJ
16
17#define INOHSZ 63
3ebac878
RE
18#if ((INOHSZ&(INOHSZ-1)) == 0)
19#define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1))
20#else
a3a9487d 21#define INOHASH(dev,ino) (((unsigned)((dev)+(ino)))%INOHSZ)
3ebac878
RE
22#endif
23
24union ihead { /* inode LRU cache, Chris Maltby */
25 union ihead *ih_head[2];
26 struct inode *ih_chain[2];
27} ihead[INOHSZ];
28
29struct inode *ifreeh, **ifreet;
5d5124a1
BJ
30
31/*
32 * Initialize hash links for inodes
33 * and build inode free list.
34 */
35ihinit()
36{
37 register int i;
75105cf0 38 register struct inode *ip = inode;
3ebac878 39 register union ihead *ih = ihead;
5d5124a1 40
3ebac878
RE
41 for (i = INOHSZ; --i >= 0; ih++) {
42 ih->ih_head[0] = ih;
43 ih->ih_head[1] = ih;
44 }
45 ifreeh = ip;
46 ifreet = &ip->i_freef;
47 ip->i_freeb = &ifreeh;
48 ip->i_forw = ip;
49 ip->i_back = ip;
50 for (i = ninode; --i > 0; ) {
51 ++ip;
52 ip->i_forw = ip;
53 ip->i_back = ip;
54 *ifreet = ip;
55 ip->i_freeb = ifreet;
56 ifreet = &ip->i_freef;
57 }
58 ip->i_freef = NULL;
5d5124a1
BJ
59}
60
3ebac878
RE
61#ifdef notdef
62/*
63 * Find an inode if it is incore.
64 * This is the equivalent, for inodes,
65 * of ``incore'' in bio.c or ``pfind'' in subr.c.
66 */
67struct inode *
68ifind(dev, ino)
69 dev_t dev;
70 ino_t ino;
71{
72 register struct inode *ip;
73 register union ihead *ih;
74
75 ih = &ihead[INOHASH(dev, ino)];
76 for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
77 if (ino==ip->i_number && dev==ip->i_dev)
78 return (ip);
79 return ((struct inode *)0);
80}
81#endif notdef
82
5d5124a1
BJ
83/*
84 * Look up an inode by device,inumber.
85 * If it is in core (in the inode structure),
86 * honor the locking protocol.
87 * If it is not in core, read it in from the
88 * specified device.
89 * If the inode is mounted on, perform
90 * the indicated indirection.
91 * In all cases, a pointer to a locked
92 * inode structure is returned.
93 *
5d5124a1
BJ
94 * panic: no imt -- if the mounted file
95 * system is not in the mount table.
96 * "cannot happen"
97 */
98struct inode *
6459ebe0 99iget(dev, fs, ino)
7494ef16 100 dev_t dev;
6459ebe0 101 register struct fs *fs;
7494ef16 102 ino_t ino;
5d5124a1 103{
32dc2b7e
RE
104 register struct inode *ip;
105 register union ihead *ih;
5d5124a1
BJ
106 register struct mount *mp;
107 register struct buf *bp;
108 register struct dinode *dp;
3ebac878 109 register struct inode *iq;
5d5124a1
BJ
110
111loop:
6459ebe0
KM
112 if (getfs(dev) != fs)
113 panic("iget: bad fs");
3ebac878
RE
114 ih = &ihead[INOHASH(dev, ino)];
115 for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
7494ef16 116 if (ino == ip->i_number && dev == ip->i_dev) {
5c2ba954 117 if ((ip->i_flag&ILOCKED) != 0) {
5d5124a1
BJ
118 ip->i_flag |= IWANT;
119 sleep((caddr_t)ip, PINOD);
120 goto loop;
121 }
7494ef16 122 if ((ip->i_flag&IMOUNT) != 0) {
6459ebe0 123 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
3ebac878
RE
124 if(mp->m_inodp == ip) {
125 dev = mp->m_dev;
126 fs = mp->m_bufp->b_un.b_fs;
127 ino = ROOTINO;
128 goto loop;
129 }
5d5124a1
BJ
130 panic("no imt");
131 }
3ebac878
RE
132 if (ip->i_count == 0) { /* ino on free list */
133 if (iq = ip->i_freef)
134 iq->i_freeb = ip->i_freeb;
135 else
136 ifreet = ip->i_freeb;
137 *ip->i_freeb = iq;
138 ip->i_freef = NULL;
139 ip->i_freeb = NULL;
140 }
5d5124a1 141 ip->i_count++;
5c2ba954 142 ip->i_flag |= ILOCKED;
5d5124a1
BJ
143 return(ip);
144 }
3ebac878
RE
145
146 if ((ip = ifreeh) == NULL) {
945fbb1b 147 tablefull("inode");
5d5124a1
BJ
148 u.u_error = ENFILE;
149 return(NULL);
150 }
3ebac878
RE
151 if (iq = ip->i_freef)
152 iq->i_freeb = &ifreeh;
153 ifreeh = iq;
154 ip->i_freef = NULL;
155 ip->i_freeb = NULL;
156 /*
157 * Now to take inode off the hash chain it was on
158 * (initially, or after an iflush, it is on a "hash chain"
159 * consisting entirely of itself, and pointed to by no-one,
160 * but that doesn't matter), and put it on the chain for
161 * its new (ino, dev) pair
162 */
32dc2b7e
RE
163 remque(ip);
164 insque(ip, ih);
b4567e9c 165#ifdef QUOTA
89045c38
RE
166 dqrele(ip->i_dquot);
167#endif
5d5124a1 168 ip->i_dev = dev;
6459ebe0 169 ip->i_fs = fs;
5d5124a1 170 ip->i_number = ino;
5c2ba954 171 ip->i_flag = ILOCKED;
5d5124a1 172 ip->i_count++;
6459ebe0 173 ip->i_lastr = 0;
954ce9b1 174 bp = bread(dev, fsbtodb(fs, itod(fs, ino)), (int)fs->fs_bsize);
5d5124a1
BJ
175 /*
176 * Check I/O errors
177 */
7494ef16 178 if ((bp->b_flags&B_ERROR) != 0) {
5d5124a1 179 brelse(bp);
3ebac878
RE
180 /*
181 * the inode doesn't contain anything useful, so it would
182 * be misleading to leave it on its hash chain.
183 * 'iput' will take care of putting it back on the free list.
184 */
32dc2b7e 185 remque(ip);
3ebac878
RE
186 ip->i_forw = ip;
187 ip->i_back = ip;
188 /*
189 * we also loose its inumber, just in case (as iput
190 * doesn't do that any more) - but as it isn't on its
191 * hash chain, I doubt if this is really necessary .. kre
192 * (probably the two methods are interchangable)
193 */
194 ip->i_number = 0;
b4567e9c 195#ifdef QUOTA
89045c38
RE
196 ip->i_dquot = NODQUOT;
197#endif
5d5124a1
BJ
198 iput(ip);
199 return(NULL);
200 }
201 dp = bp->b_un.b_dino;
6459ebe0
KM
202 dp += itoo(fs, ino);
203 ip->i_ic = dp->di_ic;
5d5124a1 204 brelse(bp);
b4567e9c 205#ifdef QUOTA
89045c38
RE
206 if (ip->i_mode == 0)
207 ip->i_dquot = NODQUOT;
208 else
209 ip->i_dquot = inoquota(ip);
210#endif
6459ebe0 211 return (ip);
5d5124a1
BJ
212}
213
214/*
215 * Decrement reference count of
216 * an inode structure.
217 * On the last reference,
218 * write the inode out and if necessary,
219 * truncate and deallocate the file.
220 */
221iput(ip)
7494ef16 222 register struct inode *ip;
5d5124a1 223{
ff56f48a 224
5c2ba954 225 if ((ip->i_flag & ILOCKED) == 0)
ff56f48a
KM
226 panic("iput");
227 iunlock(ip);
228 irele(ip);
229}
230
231irele(ip)
232 register struct inode *ip;
233{
6459ebe0 234 int mode;
5d5124a1 235
7494ef16 236 if (ip->i_count == 1) {
5c2ba954 237 ip->i_flag |= ILOCKED;
7494ef16 238 if (ip->i_nlink <= 0) {
4f083fd7 239 itrunc(ip, (u_long)0);
6459ebe0 240 mode = ip->i_mode;
5d5124a1 241 ip->i_mode = 0;
85f9cfb8 242 ip->i_rdev = 0;
5d5124a1 243 ip->i_flag |= IUPD|ICHG;
6459ebe0 244 ifree(ip, ip->i_number, mode);
b4567e9c 245#ifdef QUOTA
08d9a8ec 246 (void) chkiq(ip->i_dev, ip, ip->i_uid, 0);
89045c38
RE
247 dqrele(ip->i_dquot);
248 ip->i_dquot = NODQUOT;
249#endif
5d5124a1 250 }
3fd23f5c 251 IUPDAT(ip, &time, &time, 0);
ff56f48a 252 iunlock(ip);
3ebac878
RE
253 ip->i_flag = 0;
254 /*
255 * Put the inode on the end of the free list.
256 * Possibly in some cases it would be better to
257 * put the inode at the head of the free list,
258 * (eg: where i_mode == 0 || i_number == 0)
259 * but I will think about that later .. kre
260 * (i_number is rarely 0 - only after an i/o error in iget,
261 * where i_mode == 0, the inode will probably be wanted
262 * again soon for an ialloc, so possibly we should keep it)
263 */
264 if (ifreeh) {
265 *ifreet = ip;
266 ip->i_freeb = ifreet;
5d5124a1 267 } else {
3ebac878
RE
268 ifreeh = ip;
269 ip->i_freeb = &ifreeh;
5d5124a1 270 }
3ebac878
RE
271 ip->i_freef = NULL;
272 ifreet = &ip->i_freef;
ff56f48a 273 }
5d5124a1
BJ
274 ip->i_count--;
275}
276
277/*
278 * Check accessed and update flags on
279 * an inode structure.
280 * If any is on, update the inode
281 * with the current time.
c0bb1685
BJ
282 * If waitfor is given, then must insure
283 * i/o order so wait for write to complete.
5d5124a1 284 */
c0bb1685 285iupdat(ip, ta, tm, waitfor)
7494ef16 286 register struct inode *ip;
b32450f4 287 struct timeval *ta, *tm;
7494ef16 288 int waitfor;
5d5124a1
BJ
289{
290 register struct buf *bp;
291 struct dinode *dp;
6459ebe0 292 register struct fs *fp;
5d5124a1 293
6459ebe0
KM
294 fp = ip->i_fs;
295 if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) {
296 if (fp->fs_ronly)
5d5124a1 297 return;
6459ebe0 298 bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)),
954ce9b1 299 (int)fp->fs_bsize);
5d5124a1
BJ
300 if (bp->b_flags & B_ERROR) {
301 brelse(bp);
302 return;
303 }
7494ef16 304 if (ip->i_flag&IACC)
b32450f4 305 ip->i_atime = ta->tv_sec;
7494ef16 306 if (ip->i_flag&IUPD)
b32450f4 307 ip->i_mtime = tm->tv_sec;
7494ef16 308 if (ip->i_flag&ICHG)
3e63ef5b 309 ip->i_ctime = time.tv_sec;
5d5124a1 310 ip->i_flag &= ~(IUPD|IACC|ICHG);
c39ea692
RE
311 dp = bp->b_un.b_dino + itoo(fp, ip->i_number);
312 dp->di_ic = ip->i_ic;
c0bb1685
BJ
313 if (waitfor)
314 bwrite(bp);
315 else
316 bdwrite(bp);
5d5124a1
BJ
317 }
318}
319
9c03b2c0
SL
320#define SINGLE 0 /* index of single indirect block */
321#define DOUBLE 1 /* index of double indirect block */
322#define TRIPLE 2 /* index of triple indirect block */
5d5124a1 323/*
528f664c
SL
324 * Truncate the inode ip to at most
325 * length size. Free affected disk
326 * blocks -- the blocks of the file
327 * are removed in reverse order.
9c03b2c0
SL
328 *
329 * NB: triple indirect blocks are untested.
5d5124a1 330 */
9c03b2c0
SL
331itrunc(oip, length)
332 struct inode *oip;
4f083fd7 333 u_long length;
5d5124a1
BJ
334{
335 register i;
4f083fd7 336 register daddr_t lastblock;
9c03b2c0 337 daddr_t bn, lastiblock[NIADDR];
6459ebe0 338 register struct fs *fs;
9c03b2c0
SL
339 register struct inode *ip;
340 struct inode tip;
4f083fd7
SL
341 long blocksreleased = 0, nblocks;
342 long indirtrunc();
08d9a8ec 343 int level;
4f083fd7 344
7b2e4f05
SL
345 if (oip->i_size <= length) {
346 oip->i_flag |= ICHG|IUPD;
347 iupdat(oip, &time, &time, 1);
4f083fd7 348 return;
7b2e4f05 349 }
c0bb1685 350 /*
9c03b2c0
SL
351 * Calculate index into inode's block list of
352 * last direct and indirect blocks (if any)
353 * which we want to keep. Lastblock is -1 when
354 * the file is truncated to 0.
c0bb1685 355 */
9c03b2c0 356 fs = oip->i_fs;
4f083fd7 357 lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1;
9c03b2c0
SL
358 lastiblock[SINGLE] = lastblock - NDADDR;
359 lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs);
360 lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs);
08d9a8ec 361 nblocks = btodb(fs->fs_bsize);
6459ebe0 362 /*
9c03b2c0
SL
363 * Update size of file and block pointers
364 * on disk before we start freeing blocks.
365 * If we crash before free'ing blocks below,
366 * the blocks will be returned to the free list.
367 * lastiblock values are also normalized to -1
368 * for calls to indirtrunc below.
369 * (? fsck doesn't check validity of pointers in indirect blocks)
6459ebe0 370 */
9c03b2c0
SL
371 tip = *oip;
372 for (level = TRIPLE; level >= SINGLE; level--)
373 if (lastiblock[level] < 0) {
374 oip->i_ib[level] = 0;
375 lastiblock[level] = -1;
4f083fd7 376 }
9c03b2c0
SL
377 for (i = NDADDR - 1; i > lastblock; i--)
378 oip->i_db[i] = 0;
379 oip->i_size = length;
380 oip->i_flag |= ICHG|IUPD;
381 iupdat(oip, &time, &time, 1);
382 ip = &tip;
383
6459ebe0 384 /*
9c03b2c0 385 * Indirect blocks first.
6459ebe0 386 */
9c03b2c0
SL
387 for (level = TRIPLE; level >= SINGLE; level--) {
388 bn = ip->i_ib[level];
4f083fd7 389 if (bn != 0) {
9c03b2c0 390 blocksreleased +=
08d9a8ec 391 indirtrunc(ip, bn, lastiblock[level], level);
9c03b2c0
SL
392 if (lastiblock[level] < 0) {
393 ip->i_ib[level] = 0;
394 free(ip, bn, (off_t)fs->fs_bsize);
9c03b2c0 395 blocksreleased += nblocks;
9c03b2c0
SL
396 }
397 }
398 if (lastiblock[level] >= 0)
399 goto done;
4f083fd7 400 }
9c03b2c0 401
6459ebe0 402 /*
9c03b2c0 403 * All whole direct blocks or frags.
6459ebe0 404 */
4f083fd7
SL
405 for (i = NDADDR - 1; i > lastblock; i--) {
406 register int size;
407
6459ebe0 408 bn = ip->i_db[i];
4f083fd7 409 if (bn == 0)
5d5124a1 410 continue;
4f083fd7
SL
411 ip->i_db[i] = 0;
412 size = (off_t)blksize(fs, ip, i);
413 free(ip, bn, size);
08d9a8ec 414 blocksreleased += btodb(size);
4f083fd7 415 }
9c03b2c0
SL
416 if (lastblock < 0)
417 goto done;
418
4f083fd7
SL
419 /*
420 * Finally, look for a change in size of the
421 * last direct block; release any frags.
422 */
9c03b2c0
SL
423 bn = ip->i_db[lastblock];
424 if (bn != 0) {
425 int oldspace, newspace;
426
4f083fd7
SL
427 /*
428 * Calculate amount of space we're giving
429 * back as old block size minus new block size.
430 */
9c03b2c0 431 oldspace = blksize(fs, ip, lastblock);
4f083fd7 432 ip->i_size = length;
9c03b2c0
SL
433 newspace = blksize(fs, ip, lastblock);
434 if (newspace == 0)
435 panic("itrunc: newspace");
436 if (oldspace - newspace > 0) {
4f083fd7
SL
437 /*
438 * Block number of space to be free'd is
439 * the old block # plus the number of frags
440 * required for the storage we're keeping.
441 */
9c03b2c0
SL
442 bn += numfrags(fs, newspace);
443 free(ip, bn, oldspace - newspace);
08d9a8ec 444 blocksreleased += btodb(oldspace - newspace);
4f083fd7 445 }
5d5124a1 446 }
4f083fd7 447done:
9c03b2c0
SL
448/* BEGIN PARANOIA */
449 for (level = SINGLE; level <= TRIPLE; level++)
450 if (ip->i_ib[level] != oip->i_ib[level])
451 panic("itrunc1");
452 for (i = 0; i < NDADDR; i++)
453 if (ip->i_db[i] != oip->i_db[i])
454 panic("itrunc2");
455/* END PARANOIA */
08d9a8ec
SL
456 oip->i_blocks -= blocksreleased;
457 if (oip->i_blocks < 0) /* sanity */
458 oip->i_blocks = 0;
459 oip->i_flag |= ICHG;
b4567e9c 460#ifdef QUOTA
08d9a8ec 461 (void) chkdq(oip, -blocksreleased, 0);
89045c38 462#endif
5d5124a1
BJ
463}
464
4f083fd7
SL
465/*
466 * Release blocks associated with the inode ip and
467 * stored in the indirect block bn. Blocks are free'd
468 * in LIFO order up to (but not including) lastbn. If
9c03b2c0
SL
469 * level is greater than SINGLE, the block is an indirect
470 * block and recursive calls to indirtrunc must be used to
471 * cleanse other indirect blocks.
472 *
473 * NB: triple indirect blocks are untested.
4f083fd7 474 */
89045c38 475long
9c03b2c0 476indirtrunc(ip, bn, lastbn, level)
6459ebe0 477 register struct inode *ip;
4f083fd7 478 daddr_t bn, lastbn;
9c03b2c0 479 int level;
5d5124a1 480{
4f083fd7 481 register int i;
9c03b2c0 482 struct buf *bp, *copy;
5d5124a1 483 register daddr_t *bap;
9c03b2c0 484 register struct fs *fs = ip->i_fs;
4f083fd7 485 daddr_t nb, last;
9c03b2c0 486 long factor;
4f083fd7 487 int blocksreleased = 0, nblocks;
5d5124a1 488
9c03b2c0
SL
489 /*
490 * Calculate index in current block of last
491 * block to be kept. -1 indicates the entire
492 * block so we need not calculate the index.
493 */
494 factor = 1;
495 for (i = SINGLE; i < level; i++)
496 factor *= NINDIR(fs);
4f083fd7 497 last = lastbn;
9c03b2c0
SL
498 if (lastbn > 0)
499 last /= factor;
08d9a8ec 500 nblocks = btodb(fs->fs_bsize);
9c03b2c0
SL
501 /*
502 * Get buffer of block pointers, zero those
503 * entries corresponding to blocks to be free'd,
504 * and update on disk copy first.
505 */
506 copy = geteblk((int)fs->fs_bsize);
507 bp = bread(ip->i_dev, fsbtodb(fs, bn), (int)fs->fs_bsize);
508 if (bp->b_flags&B_ERROR) {
509 brelse(copy);
510 brelse(bp);
9c03b2c0 511 return (0);
9c03b2c0
SL
512 }
513 bap = bp->b_un.b_daddr;
514 bcopy((caddr_t)bap, (caddr_t)copy->b_un.b_daddr, (u_int)fs->fs_bsize);
515 bzero((caddr_t)&bap[last + 1],
516 (u_int)(NINDIR(fs) - (last + 1)) * sizeof (daddr_t));
517 bwrite(bp);
518 bp = copy, bap = bp->b_un.b_daddr;
4f083fd7 519
9c03b2c0
SL
520 /*
521 * Recursively free totally unused blocks.
522 */
523 for (i = NINDIR(fs) - 1; i > last; i--) {
5d5124a1 524 nb = bap[i];
4f083fd7 525 if (nb == 0)
5d5124a1 526 continue;
9c03b2c0 527 if (level > SINGLE)
4f083fd7 528 blocksreleased +=
08d9a8ec 529 indirtrunc(ip, nb, (daddr_t)-1, level - 1);
4f083fd7 530 free(ip, nb, (int)fs->fs_bsize);
4f083fd7 531 blocksreleased += nblocks;
4f083fd7 532 }
9c03b2c0
SL
533
534 /*
535 * Recursively free last partial block.
536 */
537 if (level > SINGLE && lastbn >= 0) {
538 last = lastbn % factor;
4f083fd7
SL
539 nb = bap[i];
540 if (nb != 0)
08d9a8ec 541 blocksreleased += indirtrunc(ip, nb, last, level - 1);
5d5124a1 542 }
9c03b2c0 543 brelse(bp);
4f083fd7 544 return (blocksreleased);
5d5124a1
BJ
545}
546
3ebac878
RE
547/*
548 * remove any inodes in the inode cache belonging to dev
549 *
550 * There should not be any active ones, return error if any are found
551 * (nb: this is a user error, not a system err)
552 *
553 * Also, count the references to dev by block devices - this really
554 * has nothing to do with the object of the procedure, but as we have
555 * to scan the inode table here anyway, we might as well get the
556 * extra benefit.
557 *
558 * this is called from sumount()/sys3.c when dev is being unmounted
559 */
b4567e9c 560#ifdef QUOTA
4147b3f6 561iflush(dev, iq)
89045c38 562 dev_t dev;
4147b3f6 563 struct inode *iq;
89045c38 564#else
3ebac878
RE
565iflush(dev)
566 dev_t dev;
89045c38 567#endif
3ebac878 568{
32dc2b7e 569 register struct inode *ip;
3ebac878
RE
570 register open = 0;
571
572 for (ip = inode; ip < inodeNINODE; ip++) {
b4567e9c 573#ifdef QUOTA
89045c38
RE
574 if (ip != iq && ip->i_dev == dev)
575#else
3ebac878 576 if (ip->i_dev == dev)
89045c38 577#endif
3ebac878
RE
578 if (ip->i_count)
579 return(-1);
580 else {
32dc2b7e 581 remque(ip);
3ebac878
RE
582 ip->i_forw = ip;
583 ip->i_back = ip;
584 /*
585 * as i_count == 0, the inode was on the free
586 * list already, just leave it there, it will
587 * fall off the bottom eventually. We could
588 * perhaps move it to the head of the free
589 * list, but as umounts are done so
590 * infrequently, we would gain very little,
591 * while making the code bigger.
592 */
b4567e9c 593#ifdef QUOTA
89045c38
RE
594 dqrele(ip->i_dquot);
595 ip->i_dquot = NODQUOT;
596#endif
3ebac878
RE
597 }
598 else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK &&
599 ip->i_rdev == dev)
600 open++;
601 }
602 return (open);
603}
604
d6a210b8 605/*
7494ef16 606 * Lock an inode. If its already locked, set the WANT bit and sleep.
d6a210b8 607 */
7494ef16
BJ
608ilock(ip)
609 register struct inode *ip;
d6a210b8
BJ
610{
611
5c2ba954 612 ILOCK(ip);
d6a210b8
BJ
613}
614
615/*
7494ef16 616 * Unlock an inode. If WANT bit is on, wakeup.
d6a210b8 617 */
ff56f48a 618iunlock(ip)
7494ef16 619 register struct inode *ip;
d6a210b8
BJ
620{
621
5c2ba954 622 IUNLOCK(ip);
d6a210b8 623}