print variables ($v) in hex; make $<- re-read current file
[unix-history] / usr / src / sys / ufs / lfs / lfs_inode.c
CommitLineData
89045c38 1/* lfs_inode.c 4.18 82/07/22 */
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"
12#include "../h/inline.h"
13
14#define INOHSZ 63
3ebac878
RE
15#if ((INOHSZ&(INOHSZ-1)) == 0)
16#define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1))
17#else
5d5124a1 18#define INOHASH(dev,ino) (((dev)+(ino))%INOHSZ)
3ebac878
RE
19#endif
20
21union ihead { /* inode LRU cache, Chris Maltby */
22 union ihead *ih_head[2];
23 struct inode *ih_chain[2];
24} ihead[INOHSZ];
25
26struct inode *ifreeh, **ifreet;
5d5124a1
BJ
27
28/*
29 * Initialize hash links for inodes
30 * and build inode free list.
31 */
32ihinit()
33{
34 register int i;
75105cf0 35 register struct inode *ip = inode;
3ebac878 36 register union ihead *ih = ihead;
5d5124a1 37
3ebac878
RE
38 for (i = INOHSZ; --i >= 0; ih++) {
39 ih->ih_head[0] = ih;
40 ih->ih_head[1] = ih;
41 }
42 ifreeh = ip;
43 ifreet = &ip->i_freef;
44 ip->i_freeb = &ifreeh;
45 ip->i_forw = ip;
46 ip->i_back = ip;
47 for (i = ninode; --i > 0; ) {
48 ++ip;
49 ip->i_forw = ip;
50 ip->i_back = ip;
51 *ifreet = ip;
52 ip->i_freeb = ifreet;
53 ifreet = &ip->i_freef;
54 }
55 ip->i_freef = NULL;
5d5124a1
BJ
56}
57
3ebac878
RE
58#ifdef notdef
59/*
60 * Find an inode if it is incore.
61 * This is the equivalent, for inodes,
62 * of ``incore'' in bio.c or ``pfind'' in subr.c.
63 */
64struct inode *
65ifind(dev, ino)
66 dev_t dev;
67 ino_t ino;
68{
69 register struct inode *ip;
70 register union ihead *ih;
71
72 ih = &ihead[INOHASH(dev, ino)];
73 for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
74 if (ino==ip->i_number && dev==ip->i_dev)
75 return (ip);
76 return ((struct inode *)0);
77}
78#endif notdef
79
5d5124a1
BJ
80/*
81 * Look up an inode by device,inumber.
82 * If it is in core (in the inode structure),
83 * honor the locking protocol.
84 * If it is not in core, read it in from the
85 * specified device.
86 * If the inode is mounted on, perform
87 * the indicated indirection.
88 * In all cases, a pointer to a locked
89 * inode structure is returned.
90 *
5d5124a1
BJ
91 * panic: no imt -- if the mounted file
92 * system is not in the mount table.
93 * "cannot happen"
94 */
95struct inode *
6459ebe0 96iget(dev, fs, ino)
7494ef16 97 dev_t dev;
6459ebe0 98 register struct fs *fs;
7494ef16 99 ino_t ino;
5d5124a1 100{
32dc2b7e
RE
101 register struct inode *ip;
102 register union ihead *ih;
5d5124a1
BJ
103 register struct mount *mp;
104 register struct buf *bp;
105 register struct dinode *dp;
3ebac878 106 register struct inode *iq;
5d5124a1
BJ
107
108loop:
6459ebe0
KM
109 if (getfs(dev) != fs)
110 panic("iget: bad fs");
3ebac878
RE
111 ih = &ihead[INOHASH(dev, ino)];
112 for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
7494ef16
BJ
113 if (ino == ip->i_number && dev == ip->i_dev) {
114 if ((ip->i_flag&ILOCK) != 0) {
5d5124a1
BJ
115 ip->i_flag |= IWANT;
116 sleep((caddr_t)ip, PINOD);
117 goto loop;
118 }
7494ef16 119 if ((ip->i_flag&IMOUNT) != 0) {
6459ebe0 120 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
3ebac878
RE
121 if(mp->m_inodp == ip) {
122 dev = mp->m_dev;
123 fs = mp->m_bufp->b_un.b_fs;
124 ino = ROOTINO;
125 goto loop;
126 }
5d5124a1
BJ
127 panic("no imt");
128 }
3ebac878
RE
129 if (ip->i_count == 0) { /* ino on free list */
130 if (iq = ip->i_freef)
131 iq->i_freeb = ip->i_freeb;
132 else
133 ifreet = ip->i_freeb;
134 *ip->i_freeb = iq;
135 ip->i_freef = NULL;
136 ip->i_freeb = NULL;
137 }
5d5124a1
BJ
138 ip->i_count++;
139 ip->i_flag |= ILOCK;
140 return(ip);
141 }
3ebac878
RE
142
143 if ((ip = ifreeh) == NULL) {
945fbb1b 144 tablefull("inode");
5d5124a1
BJ
145 u.u_error = ENFILE;
146 return(NULL);
147 }
3ebac878
RE
148 if (iq = ip->i_freef)
149 iq->i_freeb = &ifreeh;
150 ifreeh = iq;
151 ip->i_freef = NULL;
152 ip->i_freeb = NULL;
153 /*
154 * Now to take inode off the hash chain it was on
155 * (initially, or after an iflush, it is on a "hash chain"
156 * consisting entirely of itself, and pointed to by no-one,
157 * but that doesn't matter), and put it on the chain for
158 * its new (ino, dev) pair
159 */
32dc2b7e
RE
160 remque(ip);
161 insque(ip, ih);
89045c38
RE
162#ifdef QUOTA
163 dqrele(ip->i_dquot);
164#endif
5d5124a1 165 ip->i_dev = dev;
6459ebe0 166 ip->i_fs = fs;
5d5124a1
BJ
167 ip->i_number = ino;
168 ip->i_flag = ILOCK;
169 ip->i_count++;
6459ebe0
KM
170 ip->i_lastr = 0;
171 bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize);
5d5124a1
BJ
172 /*
173 * Check I/O errors
174 */
7494ef16 175 if ((bp->b_flags&B_ERROR) != 0) {
5d5124a1 176 brelse(bp);
3ebac878
RE
177 /*
178 * the inode doesn't contain anything useful, so it would
179 * be misleading to leave it on its hash chain.
180 * 'iput' will take care of putting it back on the free list.
181 */
32dc2b7e 182 remque(ip);
3ebac878
RE
183 ip->i_forw = ip;
184 ip->i_back = ip;
185 /*
186 * we also loose its inumber, just in case (as iput
187 * doesn't do that any more) - but as it isn't on its
188 * hash chain, I doubt if this is really necessary .. kre
189 * (probably the two methods are interchangable)
190 */
191 ip->i_number = 0;
89045c38
RE
192#ifdef QUOTA
193 ip->i_dquot = NODQUOT;
194#endif
5d5124a1
BJ
195 iput(ip);
196 return(NULL);
197 }
198 dp = bp->b_un.b_dino;
6459ebe0
KM
199 dp += itoo(fs, ino);
200 ip->i_ic = dp->di_ic;
5d5124a1 201 brelse(bp);
89045c38
RE
202#ifdef QUOTA
203 if (ip->i_mode == 0)
204 ip->i_dquot = NODQUOT;
205 else
206 ip->i_dquot = inoquota(ip);
207#endif
6459ebe0 208 return (ip);
5d5124a1
BJ
209}
210
211/*
212 * Decrement reference count of
213 * an inode structure.
214 * On the last reference,
215 * write the inode out and if necessary,
216 * truncate and deallocate the file.
217 */
218iput(ip)
7494ef16 219 register struct inode *ip;
5d5124a1 220{
ff56f48a
KM
221
222 if ((ip->i_flag & ILOCK) == 0)
223 panic("iput");
224 iunlock(ip);
225 irele(ip);
226}
227
228irele(ip)
229 register struct inode *ip;
230{
5d5124a1
BJ
231 register int i, x;
232 register struct inode *jp;
6459ebe0 233 int mode;
5d5124a1 234
7494ef16 235 if (ip->i_count == 1) {
5d5124a1 236 ip->i_flag |= ILOCK;
7494ef16 237 if (ip->i_nlink <= 0) {
5d5124a1 238 itrunc(ip);
6459ebe0 239 mode = ip->i_mode;
5d5124a1 240 ip->i_mode = 0;
85f9cfb8 241 ip->i_rdev = 0;
5d5124a1 242 ip->i_flag |= IUPD|ICHG;
6459ebe0 243 ifree(ip, ip->i_number, mode);
89045c38
RE
244#ifdef QUOTA
245 chkiq(ip->i_dev, ip, ip->i_uid, 0);
246 dqrele(ip->i_dquot);
247 ip->i_dquot = NODQUOT;
248#endif
5d5124a1 249 }
c0bb1685 250 IUPDAT(ip, &time, &time, 0);
ff56f48a 251 iunlock(ip);
3ebac878
RE
252 ip->i_flag = 0;
253 /*
254 * Put the inode on the end of the free list.
255 * Possibly in some cases it would be better to
256 * put the inode at the head of the free list,
257 * (eg: where i_mode == 0 || i_number == 0)
258 * but I will think about that later .. kre
259 * (i_number is rarely 0 - only after an i/o error in iget,
260 * where i_mode == 0, the inode will probably be wanted
261 * again soon for an ialloc, so possibly we should keep it)
262 */
263 if (ifreeh) {
264 *ifreet = ip;
265 ip->i_freeb = ifreet;
5d5124a1 266 } else {
3ebac878
RE
267 ifreeh = ip;
268 ip->i_freeb = &ifreeh;
5d5124a1 269 }
3ebac878
RE
270 ip->i_freef = NULL;
271 ifreet = &ip->i_freef;
ff56f48a 272 }
5d5124a1
BJ
273 ip->i_count--;
274}
275
276/*
277 * Check accessed and update flags on
278 * an inode structure.
279 * If any is on, update the inode
280 * with the current time.
c0bb1685
BJ
281 * If waitfor is given, then must insure
282 * i/o order so wait for write to complete.
5d5124a1 283 */
c0bb1685 284iupdat(ip, ta, tm, waitfor)
7494ef16
BJ
285 register struct inode *ip;
286 time_t *ta, *tm;
287 int waitfor;
5d5124a1
BJ
288{
289 register struct buf *bp;
290 struct dinode *dp;
6459ebe0 291 register struct fs *fp;
5d5124a1 292
6459ebe0
KM
293 fp = ip->i_fs;
294 if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) {
295 if (fp->fs_ronly)
5d5124a1 296 return;
6459ebe0
KM
297 bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)),
298 fp->fs_bsize);
5d5124a1
BJ
299 if (bp->b_flags & B_ERROR) {
300 brelse(bp);
301 return;
302 }
7494ef16 303 if (ip->i_flag&IACC)
6459ebe0 304 ip->i_atime = *ta;
7494ef16 305 if (ip->i_flag&IUPD)
6459ebe0 306 ip->i_mtime = *tm;
7494ef16 307 if (ip->i_flag&ICHG)
6459ebe0 308 ip->i_ctime = time;
5d5124a1 309 ip->i_flag &= ~(IUPD|IACC|ICHG);
c39ea692
RE
310 dp = bp->b_un.b_dino + itoo(fp, ip->i_number);
311 dp->di_ic = ip->i_ic;
c0bb1685
BJ
312 if (waitfor)
313 bwrite(bp);
314 else
315 bdwrite(bp);
5d5124a1
BJ
316 }
317}
318
319/*
320 * Free all the disk blocks associated
321 * with the specified inode structure.
322 * The blocks of the file are removed
323 * in reverse order. This FILO
324 * algorithm will tend to maintain
325 * a contiguous free list much longer
326 * than FIFO.
327 */
328itrunc(ip)
7494ef16 329 register struct inode *ip;
5d5124a1
BJ
330{
331 register i;
332 dev_t dev;
333 daddr_t bn;
c0bb1685 334 struct inode itmp;
6459ebe0 335 register struct fs *fs;
89045c38
RE
336#ifdef QUOTA
337 register long cnt = 0;
338 long tloop();
339#endif
5d5124a1 340
c0bb1685
BJ
341 /*
342 * Clean inode on disk before freeing blocks
343 * to insure no duplicates if system crashes.
344 */
345 itmp = *ip;
346 itmp.i_size = 0;
6459ebe0
KM
347 for (i = 0; i < NDADDR; i++)
348 itmp.i_db[i] = 0;
349 for (i = 0; i < NIADDR; i++)
350 itmp.i_ib[i] = 0;
c0bb1685
BJ
351 itmp.i_flag |= ICHG|IUPD;
352 iupdat(&itmp, &time, &time, 1);
353 ip->i_flag &= ~(IUPD|IACC|ICHG);
354
10abedc1
BJ
355 /*
356 * Only plain files, directories and symbolic
357 * links contain blocks.
358 */
359 i = ip->i_mode & IFMT;
360 if (i != IFREG && i != IFDIR && i != IFLNK)
361 return;
c0bb1685
BJ
362 /*
363 * Now return blocks to free list... if machine
364 * crashes, they will be harmless MISSING blocks.
365 */
5d5124a1 366 dev = ip->i_dev;
6459ebe0
KM
367 fs = ip->i_fs;
368 /*
369 * release double indirect block first
370 */
371 bn = ip->i_ib[NIADDR-1];
372 if (bn != (daddr_t)0) {
373 ip->i_ib[NIADDR - 1] = (daddr_t)0;
89045c38
RE
374#ifdef QUOTA
375 cnt +=
376#endif
377 tloop(ip, bn, 1);
6459ebe0
KM
378 }
379 /*
380 * release single indirect blocks second
381 */
382 for (i = NIADDR - 2; i >= 0; i--) {
383 bn = ip->i_ib[i];
384 if (bn != (daddr_t)0) {
385 ip->i_ib[i] = (daddr_t)0;
89045c38
RE
386#ifdef QUOTA
387 cnt +=
388#endif
389 tloop(ip, bn, 0);
6459ebe0
KM
390 }
391 }
392 /*
393 * finally release direct blocks
394 */
395 for (i = NDADDR - 1; i>=0; i--) {
89045c38
RE
396 register size;
397
6459ebe0 398 bn = ip->i_db[i];
7494ef16 399 if (bn == (daddr_t)0)
5d5124a1 400 continue;
6459ebe0 401 ip->i_db[i] = (daddr_t)0;
89045c38
RE
402 fre(ip, bn, size = (off_t)blksize(fs, ip, i));
403#ifdef QUOTA
404 cnt += size / DEV_BSIZE;
405#endif
5d5124a1
BJ
406 }
407 ip->i_size = 0;
c0bb1685
BJ
408 /*
409 * Inode was written and flags updated above.
410 * No need to modify flags here.
411 */
89045c38
RE
412#ifdef QUOTA
413 (void) chkdq(ip, -cnt, 0);
414#endif
5d5124a1
BJ
415}
416
89045c38
RE
417#ifdef QUOTA
418long
419#endif
6459ebe0
KM
420tloop(ip, bn, indflg)
421 register struct inode *ip;
422 daddr_t bn;
423 int indflg;
5d5124a1
BJ
424{
425 register i;
426 register struct buf *bp;
427 register daddr_t *bap;
6459ebe0 428 register struct fs *fs;
5d5124a1 429 daddr_t nb;
89045c38
RE
430#ifdef QUOTA
431 register long cnt = 0;
432#endif
5d5124a1
BJ
433
434 bp = NULL;
6459ebe0
KM
435 fs = ip->i_fs;
436 for (i = NINDIR(fs) - 1; i >= 0; i--) {
7494ef16 437 if (bp == NULL) {
6459ebe0 438 bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize);
5d5124a1
BJ
439 if (bp->b_flags & B_ERROR) {
440 brelse(bp);
441 return;
442 }
443 bap = bp->b_un.b_daddr;
444 }
445 nb = bap[i];
7494ef16 446 if (nb == (daddr_t)0)
5d5124a1 447 continue;
89045c38
RE
448 if (indflg) {
449#ifdef QUOTA
450 cnt +=
451#endif
452 tloop(ip, nb, 0);
453 } else {
6459ebe0 454 fre(ip, nb, fs->fs_bsize);
89045c38
RE
455#ifdef QUOTA
456 cnt += fs->fs_bsize / DEV_BSIZE;
457#endif
458 }
5d5124a1 459 }
7494ef16 460 if (bp != NULL)
5d5124a1 461 brelse(bp);
6459ebe0 462 fre(ip, bn, fs->fs_bsize);
89045c38
RE
463#ifdef QUOTA
464 cnt += fs->fs_bsize / DEV_BSIZE;
465 return(cnt);
466#endif
5d5124a1
BJ
467}
468
469/*
470 * Make a new file.
471 */
472struct inode *
473maknode(mode)
6459ebe0 474 int mode;
5d5124a1
BJ
475{
476 register struct inode *ip;
6459ebe0 477 ino_t ipref;
5d5124a1 478
6459ebe0
KM
479 if ((mode & IFMT) == IFDIR)
480 ipref = dirpref(u.u_pdir->i_fs);
481 else
482 ipref = u.u_pdir->i_number;
483 ip = ialloc(u.u_pdir, ipref, mode);
7494ef16 484 if (ip == NULL) {
5d5124a1
BJ
485 iput(u.u_pdir);
486 return(NULL);
487 }
89045c38
RE
488#ifdef QUOTA
489 if (ip->i_dquot != NODQUOT)
490 panic("maknode: dquot");
491#endif
5d5124a1 492 ip->i_flag |= IACC|IUPD|ICHG;
6459ebe0 493 if ((mode & IFMT) == 0)
5d5124a1
BJ
494 mode |= IFREG;
495 ip->i_mode = mode & ~u.u_cmask;
496 ip->i_nlink = 1;
497 ip->i_uid = u.u_uid;
4f4caf05 498 ip->i_gid = u.u_pdir->i_gid;
89045c38
RE
499#ifdef QUOTA
500 ip->i_dquot = inoquota(ip);
501#endif
c0bb1685
BJ
502
503 /*
504 * Make sure inode goes to disk before directory entry.
505 */
506 iupdat(ip, &time, &time, 1);
5d5124a1 507 wdir(ip);
6459ebe0
KM
508 if (u.u_error) {
509 /*
510 * write error occurred trying to update directory
511 * so must deallocate the inode
512 */
513 ip->i_nlink = 0;
514 ip->i_flag |= ICHG;
515 iput(ip);
516 return(NULL);
517 }
5d5124a1
BJ
518 return(ip);
519}
520
521/*
522 * Write a directory entry with
523 * parameters left as side effects
524 * to a call to namei.
525 */
526wdir(ip)
7494ef16 527 struct inode *ip;
5d5124a1 528{
6459ebe0
KM
529 register struct direct *dp, *ndp;
530 struct fs *fs;
531 struct buf *bp;
532 int lbn, bn, base;
533 int loc, dsize, spccnt, newsize;
534 char *dirbuf;
5d5124a1
BJ
535
536 u.u_dent.d_ino = ip->i_number;
5d5124a1 537 u.u_segflg = 1;
6459ebe0
KM
538 newsize = DIRSIZ(&u.u_dent);
539 /*
540 * if u.u_count == 0, a new directory block must be allocated.
541 */
542 if (u.u_count == 0) {
543 u.u_dent.d_reclen = DIRBLKSIZ;
544 u.u_count = newsize;
545 u.u_base = (caddr_t)&u.u_dent;
546 writei(u.u_pdir);
547 iput(u.u_pdir);
548 return;
549 }
550 /*
551 * must read in an existing directory block
552 * to prepare to place the new entry into it.
553 */
554 fs = u.u_pdir->i_fs;
555 lbn = lblkno(fs, u.u_offset);
556 base = blkoff(fs, u.u_offset);
557 bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count));
558 if (u.u_offset + u.u_count > u.u_pdir->i_size)
559 u.u_pdir->i_size = u.u_offset + u.u_count;
560 bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn));
561 if (bp->b_flags & B_ERROR) {
562 brelse(bp);
563 return;
564 }
565 dirbuf = bp->b_un.b_addr + base;
566 dp = (struct direct *)dirbuf;
567 dsize = DIRSIZ(dp);
568 spccnt = dp->d_reclen - dsize;
569 /*
570 * if there is insufficient room to make an entry at this point
571 * namei insures that compacting from u.u_offset for u.u_count
572 * bytes will provide the necessary space.
573 */
574 for (loc = dp->d_reclen; loc < u.u_count; ) {
575 ndp = (struct direct *)(dirbuf + loc);
576 if (dp->d_ino == 0) {
577 spccnt += dsize;
578 } else {
579 dp->d_reclen = dsize;
580 dp = (struct direct *)((char *)dp + dsize);
581 }
582 dsize = DIRSIZ(ndp);
583 spccnt += ndp->d_reclen - dsize;
584 loc += ndp->d_reclen;
585 bcopy(ndp, dp, dsize);
586 }
587 /*
588 * Update the pointer fields in the previous entry (if any),
589 * copy in the new entry, and write out the block.
590 */
591 if (dp->d_ino == 0) {
592 if (spccnt + dsize < newsize)
593 panic("wdir: compact failed");
594 u.u_dent.d_reclen = spccnt + dsize;
595 } else {
596 if (spccnt < newsize)
597 panic("wdir: compact failed");
598 u.u_dent.d_reclen = spccnt;
599 dp->d_reclen = dsize;
600 dp = (struct direct *)((char *)dp + dsize);
601 }
602 bcopy(&u.u_dent, dp, newsize);
603 bwrite(bp);
604 u.u_pdir->i_flag |= IUPD|ICHG;
5d5124a1
BJ
605 iput(u.u_pdir);
606}
d6a210b8 607
3ebac878
RE
608/*
609 * remove any inodes in the inode cache belonging to dev
610 *
611 * There should not be any active ones, return error if any are found
612 * (nb: this is a user error, not a system err)
613 *
614 * Also, count the references to dev by block devices - this really
615 * has nothing to do with the object of the procedure, but as we have
616 * to scan the inode table here anyway, we might as well get the
617 * extra benefit.
618 *
619 * this is called from sumount()/sys3.c when dev is being unmounted
620 */
89045c38
RE
621#ifdef QUOTA
622iflush(dev, qi);
623 dev_t dev;
624 struct inode *qi;
625#else
3ebac878
RE
626iflush(dev)
627 dev_t dev;
89045c38 628#endif
3ebac878 629{
32dc2b7e 630 register struct inode *ip;
3ebac878
RE
631 register open = 0;
632
633 for (ip = inode; ip < inodeNINODE; ip++) {
89045c38
RE
634#ifdef QUOTA
635 if (ip != iq && ip->i_dev == dev)
636#else
3ebac878 637 if (ip->i_dev == dev)
89045c38 638#endif
3ebac878
RE
639 if (ip->i_count)
640 return(-1);
641 else {
32dc2b7e 642 remque(ip);
3ebac878
RE
643 ip->i_forw = ip;
644 ip->i_back = ip;
645 /*
646 * as i_count == 0, the inode was on the free
647 * list already, just leave it there, it will
648 * fall off the bottom eventually. We could
649 * perhaps move it to the head of the free
650 * list, but as umounts are done so
651 * infrequently, we would gain very little,
652 * while making the code bigger.
653 */
89045c38
RE
654#ifdef QUOTA
655 dqrele(ip->i_dquot);
656 ip->i_dquot = NODQUOT;
657#endif
3ebac878
RE
658 }
659 else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK &&
660 ip->i_rdev == dev)
661 open++;
662 }
663 return (open);
664}
665
7494ef16
BJ
666#ifdef ilock
667#undef ilock
d6a210b8 668#endif
ff56f48a
KM
669#ifdef iunlock
670#undef iunlock
d6a210b8
BJ
671#endif
672/*
7494ef16 673 * Lock an inode. If its already locked, set the WANT bit and sleep.
d6a210b8 674 */
7494ef16
BJ
675ilock(ip)
676 register struct inode *ip;
d6a210b8
BJ
677{
678
7494ef16 679 while (ip->i_flag&ILOCK) {
d6a210b8
BJ
680 ip->i_flag |= IWANT;
681 sleep((caddr_t)ip, PINOD);
682 }
683 ip->i_flag |= ILOCK;
684}
685
686/*
7494ef16 687 * Unlock an inode. If WANT bit is on, wakeup.
d6a210b8 688 */
ff56f48a 689iunlock(ip)
7494ef16 690 register struct inode *ip;
d6a210b8
BJ
691{
692
693 ip->i_flag &= ~ILOCK;
7494ef16 694 if (ip->i_flag&IWANT) {
d6a210b8
BJ
695 ip->i_flag &= ~IWANT;
696 wakeup((caddr_t)ip);
697 }
698}