xref: /csrg-svn/sys/ufs/lfs/lfs_inode.c (revision 7504)
1 /*	lfs_inode.c	4.19	82/07/24	*/
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"
9 #include "../h/fs.h"
10 #include "../h/conf.h"
11 #include "../h/buf.h"
12 #include "../h/inline.h"
13 #ifdef	QUOTA
14 #include "../h/quota.h"
15 #endif
16 
17 #define	INOHSZ	63
18 #if	((INOHSZ&(INOHSZ-1)) == 0)
19 #define	INOHASH(dev,ino)	(((dev)+(ino))&(INOHSZ-1))
20 #else
21 #define	INOHASH(dev,ino)	(((dev)+(ino))%INOHSZ)
22 #endif
23 
24 union ihead {				/* inode LRU cache, Chris Maltby */
25 	union  ihead *ih_head[2];
26 	struct inode *ih_chain[2];
27 } ihead[INOHSZ];
28 
29 struct inode *ifreeh, **ifreet;
30 
31 /*
32  * Initialize hash links for inodes
33  * and build inode free list.
34  */
35 ihinit()
36 {
37 	register int i;
38 	register struct inode *ip = inode;
39 	register union  ihead *ih = ihead;
40 
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;
59 }
60 
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  */
67 struct inode *
68 ifind(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 
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  *
94  * panic: no imt -- if the mounted file
95  *	system is not in the mount table.
96  *	"cannot happen"
97  */
98 struct inode *
99 iget(dev, fs, ino)
100 	dev_t dev;
101 	register struct fs *fs;
102 	ino_t ino;
103 {
104 	register struct inode *ip;
105 	register union  ihead *ih;
106 	register struct mount *mp;
107 	register struct buf *bp;
108 	register struct dinode *dp;
109 	register struct inode *iq;
110 
111 loop:
112 	if (getfs(dev) != fs)
113 		panic("iget: bad fs");
114 	ih = &ihead[INOHASH(dev, ino)];
115 	for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
116 		if (ino == ip->i_number && dev == ip->i_dev) {
117 			if ((ip->i_flag&ILOCK) != 0) {
118 				ip->i_flag |= IWANT;
119 				sleep((caddr_t)ip, PINOD);
120 				goto loop;
121 			}
122 			if ((ip->i_flag&IMOUNT) != 0) {
123 				for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
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 					}
130 				panic("no imt");
131 			}
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 			}
141 			ip->i_count++;
142 			ip->i_flag |= ILOCK;
143 			return(ip);
144 		}
145 
146 	if ((ip = ifreeh) == NULL) {
147 		tablefull("inode");
148 		u.u_error = ENFILE;
149 		return(NULL);
150 	}
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 	 */
163 	remque(ip);
164 	insque(ip, ih);
165 #ifdef	QUOTA
166 	dqrele(ip->i_dquot);
167 #endif
168 	ip->i_dev = dev;
169 	ip->i_fs = fs;
170 	ip->i_number = ino;
171 	ip->i_flag = ILOCK;
172 	ip->i_count++;
173 	ip->i_lastr = 0;
174 	bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize);
175 	/*
176 	 * Check I/O errors
177 	 */
178 	if ((bp->b_flags&B_ERROR) != 0) {
179 		brelse(bp);
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 		 */
185 		remque(ip);
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;
195 #ifdef	QUOTA
196 		ip->i_dquot = NODQUOT;
197 #endif
198 		iput(ip);
199 		return(NULL);
200 	}
201 	dp = bp->b_un.b_dino;
202 	dp += itoo(fs, ino);
203 	ip->i_ic = dp->di_ic;
204 	brelse(bp);
205 #ifdef	QUOTA
206 	if (ip->i_mode == 0)
207 		ip->i_dquot = NODQUOT;
208 	else
209 		ip->i_dquot = inoquota(ip);
210 #endif
211 	return (ip);
212 }
213 
214 int	badinum = -1;
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  */
222 iput(ip)
223 	register struct inode *ip;
224 {
225 
226 	if ((ip->i_flag & ILOCK) == 0)
227 		panic("iput");
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 */
233 	iunlock(ip);
234 	irele(ip);
235 }
236 
237 irele(ip)
238 	register struct inode *ip;
239 {
240 	register int i, x;
241 	register struct inode *jp;
242 	int mode;
243 
244 	if (ip->i_count == 1) {
245 		ip->i_flag |= ILOCK;
246 		if (ip->i_nlink <= 0) {
247 			itrunc(ip);
248 			mode = ip->i_mode;
249 			ip->i_mode = 0;
250 			ip->i_rdev = 0;
251 			ip->i_flag |= IUPD|ICHG;
252 			ifree(ip, ip->i_number, mode);
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
258 		}
259 		IUPDAT(ip, &time, &time, 0);
260 		iunlock(ip);
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;
275 		} else {
276 			ifreeh = ip;
277 			ip->i_freeb = &ifreeh;
278 		}
279 		ip->i_freef = NULL;
280 		ifreet = &ip->i_freef;
281 	}
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.
290  * If waitfor is given, then must insure
291  * i/o order so wait for write to complete.
292  */
293 iupdat(ip, ta, tm, waitfor)
294 	register struct inode *ip;
295 	time_t *ta, *tm;
296 	int waitfor;
297 {
298 	register struct buf *bp;
299 	struct dinode *dp;
300 	register struct fs *fp;
301 
302 	fp = ip->i_fs;
303 	if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) {
304 		if (fp->fs_ronly)
305 			return;
306 		bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)),
307 			fp->fs_bsize);
308 		if (bp->b_flags & B_ERROR) {
309 			brelse(bp);
310 			return;
311 		}
312 		if (ip->i_flag&IACC)
313 			ip->i_atime = *ta;
314 		if (ip->i_flag&IUPD)
315 			ip->i_mtime = *tm;
316 		if (ip->i_flag&ICHG)
317 			ip->i_ctime = time;
318 		ip->i_flag &= ~(IUPD|IACC|ICHG);
319 		dp = bp->b_un.b_dino + itoo(fp, ip->i_number);
320 		dp->di_ic = ip->i_ic;
321 		if (waitfor)
322 			bwrite(bp);
323 		else
324 			bdwrite(bp);
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  */
337 itrunc(ip)
338 	register struct inode *ip;
339 {
340 	register i;
341 	dev_t dev;
342 	daddr_t bn;
343 	struct inode itmp;
344 	register struct fs *fs;
345 #ifdef	QUOTA
346 	register long cnt = 0;
347 	long tloop();
348 #endif
349 
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;
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;
360 	itmp.i_flag |= ICHG|IUPD;
361 	iupdat(&itmp, &time, &time, 1);
362 	ip->i_flag &= ~(IUPD|IACC|ICHG);
363 
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;
371 	/*
372 	 * Now return blocks to free list... if machine
373 	 * crashes, they will be harmless MISSING blocks.
374 	 */
375 	dev = ip->i_dev;
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;
383 #ifdef	QUOTA
384 		cnt +=
385 #endif
386 			tloop(ip, bn, 1);
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;
395 #ifdef	QUOTA
396 			cnt +=
397 #endif
398 				tloop(ip, bn, 0);
399 		}
400 	}
401 	/*
402 	 * finally release direct blocks
403 	 */
404 	for (i = NDADDR - 1; i>=0; i--) {
405 		register size;
406 
407 		bn = ip->i_db[i];
408 		if (bn == (daddr_t)0)
409 			continue;
410 		ip->i_db[i] = (daddr_t)0;
411 		fre(ip, bn, size = (off_t)blksize(fs, ip, i));
412 #ifdef	QUOTA
413 		cnt += size / DEV_BSIZE;
414 #endif
415 	}
416 	ip->i_size = 0;
417 	/*
418 	 * Inode was written and flags updated above.
419 	 * No need to modify flags here.
420 	 */
421 #ifdef	QUOTA
422 	(void) chkdq(ip, -cnt, 0);
423 #endif
424 }
425 
426 #ifdef	QUOTA
427 long
428 #endif
429 tloop(ip, bn, indflg)
430 	register struct inode *ip;
431 	daddr_t bn;
432 	int indflg;
433 {
434 	register i;
435 	register struct buf *bp;
436 	register daddr_t *bap;
437 	register struct fs *fs;
438 	daddr_t nb;
439 #ifdef	QUOTA
440 	register long cnt = 0;
441 #endif
442 
443 	bp = NULL;
444 	fs = ip->i_fs;
445 	for (i = NINDIR(fs) - 1; i >= 0; i--) {
446 		if (bp == NULL) {
447 			bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize);
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];
455 		if (nb == (daddr_t)0)
456 			continue;
457 		if (indflg) {
458 #ifdef	QUOTA
459 			cnt +=
460 #endif
461 				tloop(ip, nb, 0);
462 		} else {
463 			fre(ip, nb, fs->fs_bsize);
464 #ifdef	QUOTA
465 			cnt += fs->fs_bsize / DEV_BSIZE;
466 #endif
467 		}
468 	}
469 	if (bp != NULL)
470 		brelse(bp);
471 	fre(ip, bn, fs->fs_bsize);
472 #ifdef	QUOTA
473 	cnt += fs->fs_bsize / DEV_BSIZE;
474 	return(cnt);
475 #endif
476 }
477 
478 /*
479  * Make a new file.
480  */
481 struct inode *
482 maknode(mode)
483 	int mode;
484 {
485 	register struct inode *ip;
486 	ino_t ipref;
487 
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);
493 	if (ip == NULL) {
494 		iput(u.u_pdir);
495 		return(NULL);
496 	}
497 #ifdef	QUOTA
498 	if (ip->i_dquot != NODQUOT)
499 		panic("maknode: dquot");
500 #endif
501 	ip->i_flag |= IACC|IUPD|ICHG;
502 	if ((mode & IFMT) == 0)
503 		mode |= IFREG;
504 	ip->i_mode = mode & ~u.u_cmask;
505 	ip->i_nlink = 1;
506 	ip->i_uid = u.u_uid;
507 	ip->i_gid = u.u_pdir->i_gid;
508 #ifdef	QUOTA
509 	ip->i_dquot = inoquota(ip);
510 #endif
511 
512 	/*
513 	 * Make sure inode goes to disk before directory entry.
514 	 */
515 	iupdat(ip, &time, &time, 1);
516 	wdir(ip);
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 	}
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  */
535 wdir(ip)
536 	struct inode *ip;
537 {
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;
544 
545 	u.u_dent.d_ino = ip->i_number;
546 	u.u_segflg = 1;
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;
555 /*ZZ*/if((u.u_offset&0x1ff))panic("wdir: newblk");
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)
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);
573 		u.u_pdir->i_size = u.u_offset + u.u_count;
574 /*ZZ*/}
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;
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);
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)
612 			panic("wdir: compact failed (1)");
613 /*ZZ*/if(spccnt+dsize>512)panic("wdir: compact screwup");
614 		u.u_dent.d_reclen = spccnt + dsize;
615 	} else {
616 		if (spccnt < newsize)
617 			panic("wdir: compact failed (2)");
618 		u.u_dent.d_reclen = spccnt;
619 /*ZZ*/if ((((char *)dp-bp->b_un.b_addr)&0x1ff)+dsize>512) panic("wdir: reclen");
620 		dp->d_reclen = dsize;
621 		dp = (struct direct *)((char *)dp + dsize);
622 	}
623 /*ZZ*/if((((char*)dp-bp->b_un.b_addr)&0x1ff)+u.u_dent.d_reclen>512)panic("wdir: botch");
624 	bcopy(&u.u_dent, dp, newsize);
625 	bwrite(bp);
626 	u.u_pdir->i_flag |= IUPD|ICHG;
627 	iput(u.u_pdir);
628 }
629 
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  */
643 #ifdef	QUOTA
644 iflush(dev, iq)
645 	dev_t dev;
646 	struct inode *iq;
647 #else
648 iflush(dev)
649 	dev_t dev;
650 #endif
651 {
652 	register struct inode *ip;
653 	register open = 0;
654 
655 	for (ip = inode; ip < inodeNINODE; ip++) {
656 #ifdef	QUOTA
657 		if (ip != iq && ip->i_dev == dev)
658 #else
659 		if (ip->i_dev == dev)
660 #endif
661 			if (ip->i_count)
662 				return(-1);
663 			else {
664 				remque(ip);
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 				 */
676 #ifdef	QUOTA
677 				dqrele(ip->i_dquot);
678 				ip->i_dquot = NODQUOT;
679 #endif
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 
688 #ifdef ilock
689 #undef ilock
690 #endif
691 #ifdef iunlock
692 #undef iunlock
693 #endif
694 /*
695  * Lock an inode. If its already locked, set the WANT bit and sleep.
696  */
697 ilock(ip)
698 	register struct inode *ip;
699 {
700 
701 	while (ip->i_flag&ILOCK) {
702 		ip->i_flag |= IWANT;
703 		sleep((caddr_t)ip, PINOD);
704 	}
705 	ip->i_flag |= ILOCK;
706 }
707 
708 /*
709  * Unlock an inode.  If WANT bit is on, wakeup.
710  */
711 iunlock(ip)
712 	register struct inode *ip;
713 {
714 
715 	ip->i_flag &= ~ILOCK;
716 	if (ip->i_flag&IWANT) {
717 		ip->i_flag &= ~IWANT;
718 		wakeup((caddr_t)ip);
719 	}
720 }
721