xref: /csrg-svn/sys/ufs/lfs/lfs_inode.c (revision 7334)
1 /*	lfs_inode.c	4.13	82/06/29	*/
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 
14 #define	INOHSZ	63
15 #if	((INOHSZ&(INOHSZ-1)) == 0)
16 #define	INOHASH(dev,ino)	(((dev)+(ino))&(INOHSZ-1))
17 #else
18 #define	INOHASH(dev,ino)	(((dev)+(ino))%INOHSZ)
19 #endif
20 
21 union ihead {				/* inode LRU cache, Chris Maltby */
22 	union  ihead *ih_head[2];
23 	struct inode *ih_chain[2];
24 } ihead[INOHSZ];
25 
26 struct inode *ifreeh, **ifreet;
27 
28 /*
29  * Initialize hash links for inodes
30  * and build inode free list.
31  */
32 ihinit()
33 {
34 	register int i;
35 	register struct inode *ip = inode;
36 	register union  ihead *ih = ihead;
37 
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;
56 }
57 
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  */
64 struct inode *
65 ifind(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 
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  *
91  * panic: no imt -- if the mounted file
92  *	system is not in the mount table.
93  *	"cannot happen"
94  */
95 struct inode *
96 iget(dev, fs, ino)
97 	dev_t dev;
98 	register struct fs *fs;
99 	ino_t ino;
100 {
101 	register struct inode *ip;	/* known to be r11 - see "asm" below */
102 	register union  ihead *ih;	/* known to be r10 - see "asm" below */
103 	register struct mount *mp;
104 	register struct buf *bp;
105 	register struct dinode *dp;
106 	register struct inode *iq;
107 
108 loop:
109 	if (getfs(dev) != fs)
110 		panic("iget: bad fs");
111 	ih = &ihead[INOHASH(dev, ino)];
112 	for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw)
113 		if (ino == ip->i_number && dev == ip->i_dev) {
114 			if ((ip->i_flag&ILOCK) != 0) {
115 				ip->i_flag |= IWANT;
116 				sleep((caddr_t)ip, PINOD);
117 				goto loop;
118 			}
119 			if ((ip->i_flag&IMOUNT) != 0) {
120 				for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
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 					}
127 				panic("no imt");
128 			}
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 			}
138 			ip->i_count++;
139 			ip->i_flag |= ILOCK;
140 			return(ip);
141 		}
142 
143 	if ((ip = ifreeh) == NULL) {
144 		tablefull("inode");
145 		u.u_error = ENFILE;
146 		return(NULL);
147 	}
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 	 */
160 #ifndef	UNFAST
161 	asm("remque	(r11),r0");
162 	asm("insque	(r11),(r10)");
163 #else
164 		/* remque */
165 	ip->i_back->i_forw = ip->i_forw;
166 	ip->i_forw->i_back = ip->i_back;
167 		/* insque */
168 	ip->i_forw = ih->ih_chain[0];
169 	ip->i_back = (struct inode *)ih;
170 	ih->ih_chain[0]->i_back = ip;
171 	ih->ih_chain[0] = ip;
172 #endif
173 	ip->i_dev = dev;
174 	ip->i_fs = fs;
175 	ip->i_number = ino;
176 	ip->i_flag = ILOCK;
177 	ip->i_count++;
178 	ip->i_lastr = 0;
179 	bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize);
180 	/*
181 	 * Check I/O errors
182 	 */
183 	if ((bp->b_flags&B_ERROR) != 0) {
184 		brelse(bp);
185 		/*
186 		 * the inode doesn't contain anything useful, so it would
187 		 * be misleading to leave it on its hash chain.
188 		 * 'iput' will take care of putting it back on the free list.
189 		 */
190 #ifndef	UNFAST
191 		asm("remque	(r11),r0");
192 #else
193 		ip->i_back->i_forw = ip->i_forw;
194 		ip->i_forw->i_back = ip->i_back;
195 #endif
196 		ip->i_forw = ip;
197 		ip->i_back = ip;
198 		/*
199 		 * we also loose its inumber, just in case (as iput
200 		 * doesn't do that any more) - but as it isn't on its
201 		 * hash chain, I doubt if this is really necessary .. kre
202 		 * (probably the two methods are interchangable)
203 		 */
204 		ip->i_number = 0;
205 		iput(ip);
206 		return(NULL);
207 	}
208 	dp = bp->b_un.b_dino;
209 	dp += itoo(fs, ino);
210 	ip->i_ic = dp->di_ic;
211 	brelse(bp);
212 	return (ip);
213 }
214 
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 	iunlock(ip);
229 	irele(ip);
230 }
231 
232 irele(ip)
233 	register struct inode *ip;
234 {
235 	register int i, x;
236 	register struct inode *jp;
237 	int mode;
238 
239 	if (ip->i_count == 1) {
240 		ip->i_flag |= ILOCK;
241 		if (ip->i_nlink <= 0) {
242 			itrunc(ip);
243 			mode = ip->i_mode;
244 			ip->i_mode = 0;
245 			ip->i_flag |= IUPD|ICHG;
246 			ifree(ip, ip->i_number, mode);
247 		}
248 		IUPDAT(ip, &time, &time, 0);
249 		iunlock(ip);
250 		ip->i_flag = 0;
251 		/*
252 		 * Put the inode on the end of the free list.
253 		 * Possibly in some cases it would be better to
254 		 * put the inode at the head of the free list,
255 		 * (eg: where i_mode == 0 || i_number == 0)
256 		 * but I will think about that later .. kre
257 		 * (i_number is rarely 0 - only after an i/o error in iget,
258 		 * where i_mode == 0, the inode will probably be wanted
259 		 * again soon for an ialloc, so possibly we should keep it)
260 		 */
261 		if (ifreeh) {
262 			*ifreet = ip;
263 			ip->i_freeb = ifreet;
264 		} else {
265 			ifreeh = ip;
266 			ip->i_freeb = &ifreeh;
267 		}
268 		ip->i_freef = NULL;
269 		ifreet = &ip->i_freef;
270 	}
271 	ip->i_count--;
272 }
273 
274 /*
275  * Check accessed and update flags on
276  * an inode structure.
277  * If any is on, update the inode
278  * with the current time.
279  * If waitfor is given, then must insure
280  * i/o order so wait for write to complete.
281  */
282 iupdat(ip, ta, tm, waitfor)
283 	register struct inode *ip;
284 	time_t *ta, *tm;
285 	int waitfor;
286 {
287 	register struct buf *bp;
288 	struct dinode *dp;
289 	register struct fs *fp;
290 
291 	fp = ip->i_fs;
292 	if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) {
293 		if (fp->fs_ronly)
294 			return;
295 		bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)),
296 			fp->fs_bsize);
297 		if (bp->b_flags & B_ERROR) {
298 			brelse(bp);
299 			return;
300 		}
301 		if (ip->i_flag&IACC)
302 			ip->i_atime = *ta;
303 		if (ip->i_flag&IUPD)
304 			ip->i_mtime = *tm;
305 		if (ip->i_flag&ICHG)
306 			ip->i_ctime = time;
307 		ip->i_flag &= ~(IUPD|IACC|ICHG);
308 		if (waitfor)
309 			bwrite(bp);
310 		else
311 			bdwrite(bp);
312 	}
313 }
314 
315 /*
316  * Free all the disk blocks associated
317  * with the specified inode structure.
318  * The blocks of the file are removed
319  * in reverse order. This FILO
320  * algorithm will tend to maintain
321  * a contiguous free list much longer
322  * than FIFO.
323  */
324 itrunc(ip)
325 	register struct inode *ip;
326 {
327 	register i;
328 	dev_t dev;
329 	daddr_t bn;
330 	struct inode itmp;
331 	register struct fs *fs;
332 
333 	i = ip->i_mode & IFMT;
334 	if (i != IFREG && i != IFDIR && i != IFLNK)
335 		return;
336 	/*
337 	 * Clean inode on disk before freeing blocks
338 	 * to insure no duplicates if system crashes.
339 	 */
340 	itmp = *ip;
341 	itmp.i_size = 0;
342 	for (i = 0; i < NDADDR; i++)
343 		itmp.i_db[i] = 0;
344 	for (i = 0; i < NIADDR; i++)
345 		itmp.i_ib[i] = 0;
346 	itmp.i_flag |= ICHG|IUPD;
347 	iupdat(&itmp, &time, &time, 1);
348 	ip->i_flag &= ~(IUPD|IACC|ICHG);
349 
350 	/*
351 	 * Now return blocks to free list... if machine
352 	 * crashes, they will be harmless MISSING blocks.
353 	 */
354 	dev = ip->i_dev;
355 	fs = ip->i_fs;
356 	/*
357 	 * release double indirect block first
358 	 */
359 	bn = ip->i_ib[NIADDR-1];
360 	if (bn != (daddr_t)0) {
361 		ip->i_ib[NIADDR - 1] = (daddr_t)0;
362 		tloop(ip, bn, 1);
363 	}
364 	/*
365 	 * release single indirect blocks second
366 	 */
367 	for (i = NIADDR - 2; i >= 0; i--) {
368 		bn = ip->i_ib[i];
369 		if (bn != (daddr_t)0) {
370 			ip->i_ib[i] = (daddr_t)0;
371 			tloop(ip, bn, 0);
372 		}
373 	}
374 	/*
375 	 * finally release direct blocks
376 	 */
377 	for (i = NDADDR - 1; i>=0; i--) {
378 		bn = ip->i_db[i];
379 		if (bn == (daddr_t)0)
380 			continue;
381 		ip->i_db[i] = (daddr_t)0;
382 		fre(ip, bn, (off_t)blksize(fs, ip, i));
383 	}
384 	ip->i_size = 0;
385 	/*
386 	 * Inode was written and flags updated above.
387 	 * No need to modify flags here.
388 	 */
389 }
390 
391 tloop(ip, bn, indflg)
392 	register struct inode *ip;
393 	daddr_t bn;
394 	int indflg;
395 {
396 	register i;
397 	register struct buf *bp;
398 	register daddr_t *bap;
399 	register struct fs *fs;
400 	daddr_t nb;
401 
402 	bp = NULL;
403 	fs = ip->i_fs;
404 	for (i = NINDIR(fs) - 1; i >= 0; i--) {
405 		if (bp == NULL) {
406 			bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize);
407 			if (bp->b_flags & B_ERROR) {
408 				brelse(bp);
409 				return;
410 			}
411 			bap = bp->b_un.b_daddr;
412 		}
413 		nb = bap[i];
414 		if (nb == (daddr_t)0)
415 			continue;
416 		if (indflg)
417 			tloop(ip, nb, 0);
418 		else
419 			fre(ip, nb, fs->fs_bsize);
420 	}
421 	if (bp != NULL)
422 		brelse(bp);
423 	fre(ip, bn, fs->fs_bsize);
424 }
425 
426 /*
427  * Make a new file.
428  */
429 struct inode *
430 maknode(mode)
431 	int mode;
432 {
433 	register struct inode *ip;
434 	ino_t ipref;
435 
436 	if ((mode & IFMT) == IFDIR)
437 		ipref = dirpref(u.u_pdir->i_fs);
438 	else
439 		ipref = u.u_pdir->i_number;
440 	ip = ialloc(u.u_pdir, ipref, mode);
441 	if (ip == NULL) {
442 		iput(u.u_pdir);
443 		return(NULL);
444 	}
445 	ip->i_flag |= IACC|IUPD|ICHG;
446 	if ((mode & IFMT) == 0)
447 		mode |= IFREG;
448 	ip->i_mode = mode & ~u.u_cmask;
449 	ip->i_nlink = 1;
450 	ip->i_uid = u.u_uid;
451 	ip->i_gid = u.u_pdir->i_gid;
452 
453 	/*
454 	 * Make sure inode goes to disk before directory entry.
455 	 */
456 	iupdat(ip, &time, &time, 1);
457 	wdir(ip);
458 	if (u.u_error) {
459 		/*
460 		 * write error occurred trying to update directory
461 		 * so must deallocate the inode
462 		 */
463 		ip->i_nlink = 0;
464 		ip->i_flag |= ICHG;
465 		iput(ip);
466 		return(NULL);
467 	}
468 	return(ip);
469 }
470 
471 /*
472  * Write a directory entry with
473  * parameters left as side effects
474  * to a call to namei.
475  */
476 wdir(ip)
477 	struct inode *ip;
478 {
479 	register struct direct *dp, *ndp;
480 	struct fs *fs;
481 	struct buf *bp;
482 	int lbn, bn, base;
483 	int loc, dsize, spccnt, newsize;
484 	char *dirbuf;
485 
486 	u.u_dent.d_ino = ip->i_number;
487 	u.u_segflg = 1;
488 	newsize = DIRSIZ(&u.u_dent);
489 	/*
490 	 * if u.u_count == 0, a new directory block must be allocated.
491 	 */
492 	if (u.u_count == 0) {
493 		u.u_dent.d_reclen = DIRBLKSIZ;
494 		u.u_count = newsize;
495 		u.u_base = (caddr_t)&u.u_dent;
496 		writei(u.u_pdir);
497 		iput(u.u_pdir);
498 		return;
499 	}
500 	/*
501 	 * must read in an existing directory block
502 	 * to prepare to place the new entry into it.
503 	 */
504 	fs = u.u_pdir->i_fs;
505 	lbn = lblkno(fs, u.u_offset);
506 	base = blkoff(fs, u.u_offset);
507 	bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count));
508 	if (u.u_offset + u.u_count > u.u_pdir->i_size)
509 		u.u_pdir->i_size = u.u_offset + u.u_count;
510 	bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn));
511 	if (bp->b_flags & B_ERROR) {
512 		brelse(bp);
513 		return;
514 	}
515 	dirbuf = bp->b_un.b_addr + base;
516 	dp = (struct direct *)dirbuf;
517 	dsize = DIRSIZ(dp);
518 	spccnt = dp->d_reclen - dsize;
519 	/*
520 	 * if there is insufficient room to make an entry at this point
521 	 * namei insures that compacting from u.u_offset for u.u_count
522 	 * bytes will provide the necessary space.
523 	 */
524 	for (loc = dp->d_reclen; loc < u.u_count; ) {
525 		ndp = (struct direct *)(dirbuf + loc);
526 		if (dp->d_ino == 0) {
527 			spccnt += dsize;
528 		} else {
529 			dp->d_reclen = dsize;
530 			dp = (struct direct *)((char *)dp + dsize);
531 		}
532 		dsize = DIRSIZ(ndp);
533 		spccnt += ndp->d_reclen - dsize;
534 		loc += ndp->d_reclen;
535 		bcopy(ndp, dp, dsize);
536 	}
537 	/*
538 	 * Update the pointer fields in the previous entry (if any),
539 	 * copy in the new entry, and write out the block.
540 	 */
541 	if (dp->d_ino == 0) {
542 		if (spccnt + dsize < newsize)
543 			panic("wdir: compact failed");
544 		u.u_dent.d_reclen = spccnt + dsize;
545 	} else {
546 		if (spccnt < newsize)
547 			panic("wdir: compact failed");
548 		u.u_dent.d_reclen = spccnt;
549 		dp->d_reclen = dsize;
550 		dp = (struct direct *)((char *)dp + dsize);
551 	}
552 	bcopy(&u.u_dent, dp, newsize);
553 	bwrite(bp);
554 	u.u_pdir->i_flag |= IUPD|ICHG;
555 	iput(u.u_pdir);
556 }
557 
558 /*
559  * remove any inodes in the inode cache belonging to dev
560  *
561  * There should not be any active ones, return error if any are found
562  * (nb: this is a user error, not a system err)
563  *
564  * Also, count the references to dev by block devices - this really
565  * has nothing to do with the object of the procedure, but as we have
566  * to scan the inode table here anyway, we might as well get the
567  * extra benefit.
568  *
569  * this is called from sumount()/sys3.c when dev is being unmounted
570  */
571 iflush(dev)
572 	dev_t dev;
573 {
574 	register struct inode *ip;	/* known to be r11 - see 'asm' below */
575 	register open = 0;
576 
577 	for (ip = inode; ip < inodeNINODE; ip++) {
578 		if (ip->i_dev == dev)
579 			if (ip->i_count)
580 				return(-1);
581 			else {
582 #ifndef	UNFAST
583 				asm("remque	(r11),r0");
584 #else
585 				ip->i_back->i_forw = ip->i_forw;
586 				ip->i_forw->i_back = ip->i_back;
587 #endif
588 				ip->i_forw = ip;
589 				ip->i_back = ip;
590 				/*
591 				 * as i_count == 0, the inode was on the free
592 				 * list already, just leave it there, it will
593 				 * fall off the bottom eventually. We could
594 				 * perhaps move it to the head of the free
595 				 * list, but as umounts are done so
596 				 * infrequently, we would gain very little,
597 				 * while making the code bigger.
598 				 */
599 			}
600 		else if (ip->i_count && (ip->i_mode&IFMT)==IFBLK &&
601 		    ip->i_rdev == dev)
602 			open++;
603 	}
604 	return (open);
605 }
606 
607 #ifdef ilock
608 #undef ilock
609 #endif
610 #ifdef iunlock
611 #undef iunlock
612 #endif
613 /*
614  * Lock an inode. If its already locked, set the WANT bit and sleep.
615  */
616 ilock(ip)
617 	register struct inode *ip;
618 {
619 
620 	while (ip->i_flag&ILOCK) {
621 		ip->i_flag |= IWANT;
622 		sleep((caddr_t)ip, PINOD);
623 	}
624 	ip->i_flag |= ILOCK;
625 }
626 
627 /*
628  * Unlock an inode.  If WANT bit is on, wakeup.
629  */
630 iunlock(ip)
631 	register struct inode *ip;
632 {
633 
634 	ip->i_flag &= ~ILOCK;
635 	if (ip->i_flag&IWANT) {
636 		ip->i_flag &= ~IWANT;
637 		wakeup((caddr_t)ip);
638 	}
639 }
640