merge with calder
[unix-history] / usr / src / sys / ufs / ffs / ufs_inode.c
CommitLineData
4147b3f6 1/* ufs_inode.c 4.19 82/07/24 */
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"
4147b3f6
BJ
13#ifdef QUOTA
14#include "../h/quota.h"
15#endif
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
5d5124a1 21#define INOHASH(dev,ino) (((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
BJ
116 if (ino == ip->i_number && dev == ip->i_dev) {
117 if ((ip->i_flag&ILOCK) != 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
BJ
141 ip->i_count++;
142 ip->i_flag |= ILOCK;
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);
89045c38
RE
165#ifdef QUOTA
166 dqrele(ip->i_dquot);
167#endif
5d5124a1 168 ip->i_dev = dev;
6459ebe0 169 ip->i_fs = fs;
5d5124a1
BJ
170 ip->i_number = ino;
171 ip->i_flag = ILOCK;
172 ip->i_count++;
6459ebe0
KM
173 ip->i_lastr = 0;
174 bp = bread(dev, fsbtodb(fs, itod(fs, ino)), 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;
89045c38
RE
195#ifdef QUOTA
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);
89045c38
RE
205#ifdef QUOTA
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
4147b3f6 214int badinum = -1;
5d5124a1
BJ
215/*
216 * Decrement reference count of
217 * an inode structure.
218 * On the last reference,
219 * write the inode out and if necessary,
220 * truncate and deallocate the file.
221 */
222iput(ip)
7494ef16 223 register struct inode *ip;
5d5124a1 224{
ff56f48a
KM
225
226 if ((ip->i_flag & ILOCK) == 0)
227 panic("iput");
4147b3f6
BJ
228/* XXX */
229 if (ip->i_number == badinum && (ip->i_mode&IFMT) == IFCHR &&
230 (major(ip->i_dev) != 3 || minor(ip->i_dev) != 2))
231 panic("/dev/null");
232/* XXX */
ff56f48a
KM
233 iunlock(ip);
234 irele(ip);
235}
236
237irele(ip)
238 register struct inode *ip;
239{
5d5124a1
BJ
240 register int i, x;
241 register struct inode *jp;
6459ebe0 242 int mode;
5d5124a1 243
7494ef16 244 if (ip->i_count == 1) {
5d5124a1 245 ip->i_flag |= ILOCK;
7494ef16 246 if (ip->i_nlink <= 0) {
5d5124a1 247 itrunc(ip);
6459ebe0 248 mode = ip->i_mode;
5d5124a1 249 ip->i_mode = 0;
85f9cfb8 250 ip->i_rdev = 0;
5d5124a1 251 ip->i_flag |= IUPD|ICHG;
6459ebe0 252 ifree(ip, ip->i_number, mode);
89045c38
RE
253#ifdef QUOTA
254 chkiq(ip->i_dev, ip, ip->i_uid, 0);
255 dqrele(ip->i_dquot);
256 ip->i_dquot = NODQUOT;
257#endif
5d5124a1 258 }
c0bb1685 259 IUPDAT(ip, &time, &time, 0);
ff56f48a 260 iunlock(ip);
3ebac878
RE
261 ip->i_flag = 0;
262 /*
263 * Put the inode on the end of the free list.
264 * Possibly in some cases it would be better to
265 * put the inode at the head of the free list,
266 * (eg: where i_mode == 0 || i_number == 0)
267 * but I will think about that later .. kre
268 * (i_number is rarely 0 - only after an i/o error in iget,
269 * where i_mode == 0, the inode will probably be wanted
270 * again soon for an ialloc, so possibly we should keep it)
271 */
272 if (ifreeh) {
273 *ifreet = ip;
274 ip->i_freeb = ifreet;
5d5124a1 275 } else {
3ebac878
RE
276 ifreeh = ip;
277 ip->i_freeb = &ifreeh;
5d5124a1 278 }
3ebac878
RE
279 ip->i_freef = NULL;
280 ifreet = &ip->i_freef;
ff56f48a 281 }
5d5124a1
BJ
282 ip->i_count--;
283}
284
285/*
286 * Check accessed and update flags on
287 * an inode structure.
288 * If any is on, update the inode
289 * with the current time.
c0bb1685
BJ
290 * If waitfor is given, then must insure
291 * i/o order so wait for write to complete.
5d5124a1 292 */
c0bb1685 293iupdat(ip, ta, tm, waitfor)
7494ef16
BJ
294 register struct inode *ip;
295 time_t *ta, *tm;
296 int waitfor;
5d5124a1
BJ
297{
298 register struct buf *bp;
299 struct dinode *dp;
6459ebe0 300 register struct fs *fp;
5d5124a1 301
6459ebe0
KM
302 fp = ip->i_fs;
303 if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) {
304 if (fp->fs_ronly)
5d5124a1 305 return;
6459ebe0
KM
306 bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)),
307 fp->fs_bsize);
5d5124a1
BJ
308 if (bp->b_flags & B_ERROR) {
309 brelse(bp);
310 return;
311 }
7494ef16 312 if (ip->i_flag&IACC)
6459ebe0 313 ip->i_atime = *ta;
7494ef16 314 if (ip->i_flag&IUPD)
6459ebe0 315 ip->i_mtime = *tm;
7494ef16 316 if (ip->i_flag&ICHG)
6459ebe0 317 ip->i_ctime = time;
5d5124a1 318 ip->i_flag &= ~(IUPD|IACC|ICHG);
c39ea692
RE
319 dp = bp->b_un.b_dino + itoo(fp, ip->i_number);
320 dp->di_ic = ip->i_ic;
c0bb1685
BJ
321 if (waitfor)
322 bwrite(bp);
323 else
324 bdwrite(bp);
5d5124a1
BJ
325 }
326}
327
328/*
329 * Free all the disk blocks associated
330 * with the specified inode structure.
331 * The blocks of the file are removed
332 * in reverse order. This FILO
333 * algorithm will tend to maintain
334 * a contiguous free list much longer
335 * than FIFO.
336 */
337itrunc(ip)
7494ef16 338 register struct inode *ip;
5d5124a1
BJ
339{
340 register i;
341 dev_t dev;
342 daddr_t bn;
c0bb1685 343 struct inode itmp;
6459ebe0 344 register struct fs *fs;
89045c38
RE
345#ifdef QUOTA
346 register long cnt = 0;
347 long tloop();
348#endif
5d5124a1 349
c0bb1685
BJ
350 /*
351 * Clean inode on disk before freeing blocks
352 * to insure no duplicates if system crashes.
353 */
354 itmp = *ip;
355 itmp.i_size = 0;
6459ebe0
KM
356 for (i = 0; i < NDADDR; i++)
357 itmp.i_db[i] = 0;
358 for (i = 0; i < NIADDR; i++)
359 itmp.i_ib[i] = 0;
c0bb1685
BJ
360 itmp.i_flag |= ICHG|IUPD;
361 iupdat(&itmp, &time, &time, 1);
362 ip->i_flag &= ~(IUPD|IACC|ICHG);
363
10abedc1
BJ
364 /*
365 * Only plain files, directories and symbolic
366 * links contain blocks.
367 */
368 i = ip->i_mode & IFMT;
369 if (i != IFREG && i != IFDIR && i != IFLNK)
370 return;
c0bb1685
BJ
371 /*
372 * Now return blocks to free list... if machine
373 * crashes, they will be harmless MISSING blocks.
374 */
5d5124a1 375 dev = ip->i_dev;
6459ebe0
KM
376 fs = ip->i_fs;
377 /*
378 * release double indirect block first
379 */
380 bn = ip->i_ib[NIADDR-1];
381 if (bn != (daddr_t)0) {
382 ip->i_ib[NIADDR - 1] = (daddr_t)0;
89045c38
RE
383#ifdef QUOTA
384 cnt +=
385#endif
386 tloop(ip, bn, 1);
6459ebe0
KM
387 }
388 /*
389 * release single indirect blocks second
390 */
391 for (i = NIADDR - 2; i >= 0; i--) {
392 bn = ip->i_ib[i];
393 if (bn != (daddr_t)0) {
394 ip->i_ib[i] = (daddr_t)0;
89045c38
RE
395#ifdef QUOTA
396 cnt +=
397#endif
398 tloop(ip, bn, 0);
6459ebe0
KM
399 }
400 }
401 /*
402 * finally release direct blocks
403 */
404 for (i = NDADDR - 1; i>=0; i--) {
89045c38
RE
405 register size;
406
6459ebe0 407 bn = ip->i_db[i];
7494ef16 408 if (bn == (daddr_t)0)
5d5124a1 409 continue;
6459ebe0 410 ip->i_db[i] = (daddr_t)0;
89045c38
RE
411 fre(ip, bn, size = (off_t)blksize(fs, ip, i));
412#ifdef QUOTA
413 cnt += size / DEV_BSIZE;
414#endif
5d5124a1
BJ
415 }
416 ip->i_size = 0;
c0bb1685
BJ
417 /*
418 * Inode was written and flags updated above.
419 * No need to modify flags here.
420 */
89045c38
RE
421#ifdef QUOTA
422 (void) chkdq(ip, -cnt, 0);
423#endif
5d5124a1
BJ
424}
425
89045c38
RE
426#ifdef QUOTA
427long
428#endif
6459ebe0
KM
429tloop(ip, bn, indflg)
430 register struct inode *ip;
431 daddr_t bn;
432 int indflg;
5d5124a1
BJ
433{
434 register i;
435 register struct buf *bp;
436 register daddr_t *bap;
6459ebe0 437 register struct fs *fs;
5d5124a1 438 daddr_t nb;
89045c38
RE
439#ifdef QUOTA
440 register long cnt = 0;
441#endif
5d5124a1
BJ
442
443 bp = NULL;
6459ebe0
KM
444 fs = ip->i_fs;
445 for (i = NINDIR(fs) - 1; i >= 0; i--) {
7494ef16 446 if (bp == NULL) {
6459ebe0 447 bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize);
5d5124a1
BJ
448 if (bp->b_flags & B_ERROR) {
449 brelse(bp);
450 return;
451 }
452 bap = bp->b_un.b_daddr;
453 }
454 nb = bap[i];
7494ef16 455 if (nb == (daddr_t)0)
5d5124a1 456 continue;
89045c38
RE
457 if (indflg) {
458#ifdef QUOTA
459 cnt +=
460#endif
461 tloop(ip, nb, 0);
462 } else {
6459ebe0 463 fre(ip, nb, fs->fs_bsize);
89045c38
RE
464#ifdef QUOTA
465 cnt += fs->fs_bsize / DEV_BSIZE;
466#endif
467 }
5d5124a1 468 }
7494ef16 469 if (bp != NULL)
5d5124a1 470 brelse(bp);
6459ebe0 471 fre(ip, bn, fs->fs_bsize);
89045c38
RE
472#ifdef QUOTA
473 cnt += fs->fs_bsize / DEV_BSIZE;
474 return(cnt);
475#endif
5d5124a1
BJ
476}
477
478/*
479 * Make a new file.
480 */
481struct inode *
482maknode(mode)
6459ebe0 483 int mode;
5d5124a1
BJ
484{
485 register struct inode *ip;
6459ebe0 486 ino_t ipref;
5d5124a1 487
6459ebe0
KM
488 if ((mode & IFMT) == IFDIR)
489 ipref = dirpref(u.u_pdir->i_fs);
490 else
491 ipref = u.u_pdir->i_number;
492 ip = ialloc(u.u_pdir, ipref, mode);
7494ef16 493 if (ip == NULL) {
5d5124a1
BJ
494 iput(u.u_pdir);
495 return(NULL);
496 }
89045c38
RE
497#ifdef QUOTA
498 if (ip->i_dquot != NODQUOT)
499 panic("maknode: dquot");
500#endif
5d5124a1 501 ip->i_flag |= IACC|IUPD|ICHG;
6459ebe0 502 if ((mode & IFMT) == 0)
5d5124a1
BJ
503 mode |= IFREG;
504 ip->i_mode = mode & ~u.u_cmask;
505 ip->i_nlink = 1;
506 ip->i_uid = u.u_uid;
4f4caf05 507 ip->i_gid = u.u_pdir->i_gid;
89045c38
RE
508#ifdef QUOTA
509 ip->i_dquot = inoquota(ip);
510#endif
c0bb1685
BJ
511
512 /*
513 * Make sure inode goes to disk before directory entry.
514 */
515 iupdat(ip, &time, &time, 1);
5d5124a1 516 wdir(ip);
6459ebe0
KM
517 if (u.u_error) {
518 /*
519 * write error occurred trying to update directory
520 * so must deallocate the inode
521 */
522 ip->i_nlink = 0;
523 ip->i_flag |= ICHG;
524 iput(ip);
525 return(NULL);
526 }
5d5124a1
BJ
527 return(ip);
528}
529
530/*
531 * Write a directory entry with
532 * parameters left as side effects
533 * to a call to namei.
534 */
535wdir(ip)
7494ef16 536 struct inode *ip;
5d5124a1 537{
6459ebe0
KM
538 register struct direct *dp, *ndp;
539 struct fs *fs;
540 struct buf *bp;
541 int lbn, bn, base;
542 int loc, dsize, spccnt, newsize;
543 char *dirbuf;
5d5124a1
BJ
544
545 u.u_dent.d_ino = ip->i_number;
5d5124a1 546 u.u_segflg = 1;
6459ebe0
KM
547 newsize = DIRSIZ(&u.u_dent);
548 /*
549 * if u.u_count == 0, a new directory block must be allocated.
550 */
551 if (u.u_count == 0) {
552 u.u_dent.d_reclen = DIRBLKSIZ;
553 u.u_count = newsize;
554 u.u_base = (caddr_t)&u.u_dent;
4147b3f6 555/*ZZ*/if((u.u_offset&0x1ff))panic("wdir: newblk");
6459ebe0
KM
556 writei(u.u_pdir);
557 iput(u.u_pdir);
558 return;
559 }
560 /*
561 * must read in an existing directory block
562 * to prepare to place the new entry into it.
563 */
564 fs = u.u_pdir->i_fs;
565 lbn = lblkno(fs, u.u_offset);
566 base = blkoff(fs, u.u_offset);
567 bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count));
568 if (u.u_offset + u.u_count > u.u_pdir->i_size)
4147b3f6
BJ
569/*ZZ*/{if((u.u_offset+u.u_count-1&~0x1ff)!=(u.u_pdir->i_size-1&~0x1ff))
570/*ZZ*/ printf("wdir i_size dir %s/%d (of=%d,cnt=%d,psz=%d))\n",
571/*ZZ*/ u.u_pdir->i_fs->fs_fsmnt,u.u_pdir->i_number,u.u_offset,
572/*ZZ*/ u.u_count,u.u_pdir->i_size);
6459ebe0 573 u.u_pdir->i_size = u.u_offset + u.u_count;
4147b3f6 574/*ZZ*/}
6459ebe0
KM
575 bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn));
576 if (bp->b_flags & B_ERROR) {
577 brelse(bp);
578 return;
579 }
580 dirbuf = bp->b_un.b_addr + base;
581 dp = (struct direct *)dirbuf;
582 dsize = DIRSIZ(dp);
583 spccnt = dp->d_reclen - dsize;
584 /*
585 * if there is insufficient room to make an entry at this point
586 * namei insures that compacting from u.u_offset for u.u_count
587 * bytes will provide the necessary space.
588 */
589 for (loc = dp->d_reclen; loc < u.u_count; ) {
590 ndp = (struct direct *)(dirbuf + loc);
591 if (dp->d_ino == 0) {
592 spccnt += dsize;
593 } else {
594 dp->d_reclen = dsize;
595 dp = (struct direct *)((char *)dp + dsize);
596 }
597 dsize = DIRSIZ(ndp);
598 spccnt += ndp->d_reclen - dsize;
4147b3f6
BJ
599/*ZZ*/if(spccnt>512)panic("wdir spccnt");
600/*ZZ*/if((loc&~0x1ff)!=(loc+ndp->d_reclen-1&~0x1ff))
601/*ZZ*/printf("wdir: compact loc %d reclen %d (dir %s/%d)\n",loc,ndp->d_reclen,
602/*ZZ*/u.u_pdir->i_fs->fs_fsmnt,u.u_pdir->i_number);
6459ebe0
KM
603 loc += ndp->d_reclen;
604 bcopy(ndp, dp, dsize);
605 }
606 /*
607 * Update the pointer fields in the previous entry (if any),
608 * copy in the new entry, and write out the block.
609 */
610 if (dp->d_ino == 0) {
611 if (spccnt + dsize < newsize)
4147b3f6
BJ
612 panic("wdir: compact failed (1)");
613/*ZZ*/if(spccnt+dsize>512)panic("wdir: compact screwup");
6459ebe0
KM
614 u.u_dent.d_reclen = spccnt + dsize;
615 } else {
616 if (spccnt < newsize)
4147b3f6 617 panic("wdir: compact failed (2)");
6459ebe0 618 u.u_dent.d_reclen = spccnt;
4147b3f6 619/*ZZ*/if ((((char *)dp-bp->b_un.b_addr)&0x1ff)+dsize>512) panic("wdir: reclen");
6459ebe0
KM
620 dp->d_reclen = dsize;
621 dp = (struct direct *)((char *)dp + dsize);
622 }
4147b3f6 623/*ZZ*/if((((char*)dp-bp->b_un.b_addr)&0x1ff)+u.u_dent.d_reclen>512)panic("wdir: botch");
6459ebe0
KM
624 bcopy(&u.u_dent, dp, newsize);
625 bwrite(bp);
626 u.u_pdir->i_flag |= IUPD|ICHG;
5d5124a1
BJ
627 iput(u.u_pdir);
628}
d6a210b8 629
3ebac878
RE
630/*
631 * remove any inodes in the inode cache belonging to dev
632 *
633 * There should not be any active ones, return error if any are found
634 * (nb: this is a user error, not a system err)
635 *
636 * Also, count the references to dev by block devices - this really
637 * has nothing to do with the object of the procedure, but as we have
638 * to scan the inode table here anyway, we might as well get the
639 * extra benefit.
640 *
641 * this is called from sumount()/sys3.c when dev is being unmounted
642 */
89045c38 643#ifdef QUOTA
4147b3f6 644iflush(dev, iq)
89045c38 645 dev_t dev;
4147b3f6 646 struct inode *iq;
89045c38 647#else
3ebac878
RE
648iflush(dev)
649 dev_t dev;
89045c38 650#endif
3ebac878 651{
32dc2b7e 652 register struct inode *ip;
3ebac878
RE
653 register open = 0;
654
655 for (ip = inode; ip < inodeNINODE; ip++) {
89045c38
RE
656#ifdef QUOTA
657 if (ip != iq && ip->i_dev == dev)
658#else
3ebac878 659 if (ip->i_dev == dev)
89045c38 660#endif
3ebac878
RE
661 if (ip->i_count)
662 return(-1);
663 else {
32dc2b7e 664 remque(ip);
3ebac878
RE
665 ip->i_forw = ip;
666 ip->i_back = ip;
667 /*
668 * as i_count == 0, the inode was on the free
669 * list already, just leave it there, it will
670 * fall off the bottom eventually. We could
671 * perhaps move it to the head of the free
672 * list, but as umounts are done so
673 * infrequently, we would gain very little,
674 * while making the code bigger.
675 */
89045c38
RE
676#ifdef QUOTA
677 dqrele(ip->i_dquot);
678 ip->i_dquot = NODQUOT;
679#endif
3ebac878
RE
680 }
681 else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK &&
682 ip->i_rdev == dev)
683 open++;
684 }
685 return (open);
686}
687
7494ef16
BJ
688#ifdef ilock
689#undef ilock
d6a210b8 690#endif
ff56f48a
KM
691#ifdef iunlock
692#undef iunlock
d6a210b8
BJ
693#endif
694/*
7494ef16 695 * Lock an inode. If its already locked, set the WANT bit and sleep.
d6a210b8 696 */
7494ef16
BJ
697ilock(ip)
698 register struct inode *ip;
d6a210b8
BJ
699{
700
7494ef16 701 while (ip->i_flag&ILOCK) {
d6a210b8
BJ
702 ip->i_flag |= IWANT;
703 sleep((caddr_t)ip, PINOD);
704 }
705 ip->i_flag |= ILOCK;
706}
707
708/*
7494ef16 709 * Unlock an inode. If WANT bit is on, wakeup.
d6a210b8 710 */
ff56f48a 711iunlock(ip)
7494ef16 712 register struct inode *ip;
d6a210b8
BJ
713{
714
715 ip->i_flag &= ~ILOCK;
7494ef16 716 if (ip->i_flag&IWANT) {
d6a210b8
BJ
717 ip->i_flag &= ~IWANT;
718 wakeup((caddr_t)ip);
719 }
720}