xref: /csrg-svn/sys/ufs/lfs/lfs_inode.c (revision 51346)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)lfs_inode.c	7.44 (Berkeley) 10/09/91
8  */
9 
10 #ifdef LOGFS
11 #include "param.h"
12 #include "systm.h"
13 #include "mount.h"
14 #include "proc.h"
15 #include "file.h"
16 #include "buf.h"
17 #include "vnode.h"
18 #include "kernel.h"
19 #include "malloc.h"
20 
21 #include "../ufs/quota.h"
22 #include "../ufs/inode.h"
23 #include "../ufs/ufsmount.h"
24 #include "../vm/vm_param.h"
25 #include "../vm/lock.h"
26 #include "lfs.h"
27 #include "lfs_extern.h"
28 
29 #define	INOHSZ	512
30 #if	((INOHSZ&(INOHSZ-1)) == 0)
31 #define	INOHASH(dev,ino)	(((dev)+(ino))&(INOHSZ-1))
32 #else
33 #define	INOHASH(dev,ino)	(((unsigned)((dev)+(ino)))%INOHSZ)
34 #endif
35 
36 union lfsihead {						/* LFS */
37 	union  lfsihead *ih_head[2];
38 	struct inode *ih_chain[2];
39 } lfsihead[INOHSZ];
40 
41 								/* LFS */
42 extern int prtactive;	/* 1 => print out reclaim of active vnodes */
43 
44 lock_data_t lfs_sync_lock;
45 
46 /*
47  * Initialize hash links for inodes.
48  */
49 int
50 lfs_init()
51 {
52 	register int i;
53 	register union lfsihead *ih = lfsihead;
54 
55 printf("lfs_init\n");
56 
57 #ifndef lint
58 	if (VN_MAXPRIVATE < sizeof(struct inode))
59 		panic("ihinit: too small");
60 #endif
61 	lock_init(&lfs_sync_lock, 1);
62 
63 	for (i = INOHSZ; --i >= 0; ih++) {
64 		ih->ih_head[0] = ih;
65 		ih->ih_head[1] = ih;
66 	}
67 #ifdef NOTLFS							/* LFS */
68 #ifdef QUOTA
69 	dqinit();
70 #endif /* QUOTA */
71 #endif
72 	return (0);
73 }
74 
75 void
76 lfs_hqueue(ip)
77 	struct inode *ip;
78 {
79 	union lfsihead *ih;
80 
81 	ih = &lfsihead[INOHASH(ip->i_dev, ip->i_number)];
82 	insque(ip, ih);
83 	ILOCK(ip);
84 }
85 
86 
87 /*
88  * Look up a UFS dinode number to find its incore vnode.
89  * If it is not in core, read it in from the specified device.
90  * If it is in core, wait for the lock bit to clear, then
91  * return the inode locked. Detection and handling of mount
92  * points must be done by the calling routine.
93  */
94 int
95 lfs_iget(xp, ino, ipp)
96 	struct inode *xp;
97 	ino_t ino;
98 	struct inode **ipp;
99 {
100 	dev_t dev = xp->i_dev;
101 	struct mount *mntp = ITOV(xp)->v_mount;
102 	register LFS *fs = VFSTOUFS(mntp)->um_lfs;		/* LFS */
103 	extern struct vnodeops spec_inodeops;
104 	register struct inode *ip, *iq;
105 	register struct vnode *vp;
106 	struct vnode *nvp;
107 	struct buf *bp;
108 	union lfsihead *ih;
109 	int error;
110 
111 printf("lfs_iget ino %d\n", ino);
112 	ih = &lfsihead[INOHASH(dev, ino)];
113 loop:
114 	for (ip = ih->ih_chain[0]; ip != (struct inode *)ih; ip = ip->i_forw) {
115 		if (ino != ip->i_number || dev != ip->i_dev)
116 			continue;
117 		if ((ip->i_flag&ILOCKED) != 0) {
118 			ip->i_flag |= IWANT;
119 			sleep((caddr_t)ip, PINOD);
120 			goto loop;
121 		}
122 		if (vget(ITOV(ip)))
123 			goto loop;
124 		*ipp = ip;
125 		return(0);
126 	}
127 
128 	/* Allocate new vnode/inode. */
129 	error = lfs_vcreate(mntp, ino, &nvp);
130 	if (error) {
131 		*ipp = 0;
132 		return (error);
133 	}
134 	ip = VTOI(nvp);
135 
136 	/*
137 	 * Put it onto its hash chain and lock it so that other requests for
138 	 * this inode will block if they arrive while we are sleeping waiting
139 	 * for old data structures to be purged or for the contents of the
140 	 * disk portion of this inode to be read.
141 	 */
142 	insque(ip, ih);
143 	ILOCK(ip);
144 
145 	/* Read in the disk contents for the inode, copy into the vnode. */
146 	if (error = bread(VFSTOUFS(mntp)->um_devvp, itod(fs, ino),
147 	    (int)fs->lfs_bsize, NOCRED, &bp)) {			/* LFS */
148 		/*
149 		 * The inode does not contain anything useful, so it would
150 		 * be misleading to leave it on its hash chain.
151 		 * Iput() will take care of putting it back on the free list.
152 		 */
153 		remque(ip);
154 		ip->i_forw = ip;
155 		ip->i_back = ip;
156 		/*
157 		 * Unlock and discard unneeded inode.
158 		 */
159 		iput(ip);
160 		brelse(bp);
161 		*ipp = 0;
162 		return (error);
163 	}
164 	ip->i_din = *lfs_ifind(fs, ino, bp->b_un.b_dino);
165 	brelse(bp);
166 
167 	/*
168 	 * Initialize the associated vnode
169 	 */
170 	vp = ITOV(ip);
171 	vp->v_type = IFTOVT(ip->i_mode);
172 	if (vp->v_type == VFIFO) {
173 #ifdef FIFO
174 		extern struct vnodeops fifo_inodeops;
175 		vp->v_op = &fifo_inodeops;
176 #else
177 		iput(ip);
178 		*ipp = 0;
179 		return (EOPNOTSUPP);
180 #endif /* FIFO */
181 	}
182 	if (vp->v_type == VCHR || vp->v_type == VBLK) {
183 		vp->v_op = &spec_inodeops;
184 		if (nvp = checkalias(vp, ip->i_rdev, mntp)) {
185 			/*
186 			 * Reinitialize aliased inode.
187 			 */
188 			vp = nvp;
189 			iq = VTOI(vp);
190 			iq->i_vnode = vp;
191 			iq->i_flag = 0;
192 			ILOCK(iq);
193 			iq->i_din = ip->i_din;
194 			iq->i_dev = dev;
195 			iq->i_number = ino;
196 			insque(iq, ih);
197 			/*
198 			 * Discard unneeded vnode
199 			 */
200 			ip->i_mode = 0;
201 			iput(ip);
202 			ip = iq;
203 		}
204 	}
205 	if (ino == ROOTINO)
206 		vp->v_flag |= VROOT;
207 
208 	VREF(ip->i_devvp);
209 
210 	*ipp = ip;
211 	return (0);
212 }
213 
214 /*
215  * Last reference to an inode, write the inode out and if necessary,
216  * truncate and deallocate the file.
217  */
218 int
219 lfs_inactive(vp, p)
220 	struct vnode *vp;
221 	struct proc *p;
222 {
223 	register struct inode *ip = VTOI(vp);
224 	int mode, error = 0;
225 
226 printf("lfs_inactive: ino %d mode %d nlink %d\n",
227 ip->i_number, ip->i_mode, ip->i_nlink);
228 
229 	if (prtactive && vp->v_usecount != 0)
230 		vprint("ufs_inactive: pushing active", vp);
231 	/*
232 	 * Get rid of inodes related to stale file handles.
233 	 */
234 	if (ip->i_mode == 0) {
235 		if ((vp->v_flag & VXLOCK) == 0)
236 			vgone(vp);
237 		return (0);
238 	}
239 	ILOCK(ip);
240 	if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
241 #ifdef QUOTA
242 		if (!getinoquota(ip))
243 			(void) chkiq(ip, -1, NOCRED, 0);
244 #endif
245 		error = lfs_itrunc(ip, (u_long)0, 0);		/* LFS */
246 		mode = ip->i_mode;
247 		ip->i_mode = 0;
248 		ip->i_rdev = 0;
249 		ip->i_flag |= IUPD|ICHG;
250 #ifdef NOTLFS							/* LFS */
251 		ifree(ip, ip->i_number, mode);
252 #else
253 		lfs_ifree(ip);
254 #endif
255 	}
256 	ITIMES(ip, &time, &time);
257 	IUNLOCK(ip);
258 	ip->i_flag = 0;
259 	/*
260 	 * If we are done with the inode, reclaim it
261 	 * so that it can be reused immediately.
262 	 */
263 	if (vp->v_usecount == 0 && ip->i_mode == 0)
264 		vgone(vp);
265 	return (error);
266 }
267 
268 #define	SINGLE	0	/* index of single indirect block */
269 #define	DOUBLE	1	/* index of double indirect block */
270 #define	TRIPLE	2	/* index of triple indirect block */
271 /*
272  * Truncate the inode ip to at most length size.  Free affected disk
273  * blocks -- the blocks of the file are removed in reverse order.
274  *
275  * NB: triple indirect blocks are untested.
276  */
277 lfs_itrunc(oip, length, flags)
278 	register struct inode *oip;
279 	u_long length;
280 	int flags;
281 {
282 	register daddr_t lastblock;
283 	daddr_t bn, lbn, lastiblock[NIADDR];
284 	register LFS *fs;					/* LFS */
285 	register struct inode *ip;
286 	struct buf *bp;
287 	int offset, osize, size, level;
288 	long count, nblocks, blocksreleased = 0;
289 	register int i;
290 	int aflags, error, allerror;
291 	struct inode tip;
292 
293 	vnode_pager_setsize(ITOV(oip), length);
294 	if (oip->i_size <= length) {
295 		oip->i_flag |= ICHG|IUPD;
296 		ITIMES(oip, &time, &time);
297 		return (0);
298 	}
299 	/*
300 	 * Calculate index into inode's block list of
301 	 * last direct and indirect blocks (if any)
302 	 * which we want to keep.  Lastblock is -1 when
303 	 * the file is truncated to 0.
304 	 */
305 	fs = oip->i_lfs;					/* LFS */
306 	lastblock = lblkno(fs, length + fs->lfs_bsize - 1) - 1;	/* LFS */
307 	lastiblock[SINGLE] = lastblock - NDADDR;
308 	lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs);
309 	lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs);
310 	nblocks = btodb(fs->lfs_bsize);				/* LFS */
311 	/*
312 	 * Update the size of the file. If the file is not being
313 	 * truncated to a block boundry, the contents of the
314 	 * partial block following the end of the file must be
315 	 * zero'ed in case it ever become accessable again because
316 	 * of subsequent file growth.
317 	 */
318 	osize = oip->i_size;
319 	offset = blkoff(fs, length);
320 	if (offset == 0) {
321 		oip->i_size = length;
322 	} else {
323 		lbn = lblkno(fs, length);
324 		aflags = B_CLRBUF;
325 		if (flags & IO_SYNC)
326 			aflags |= B_SYNC;
327 #ifdef QUOTA
328 		if (error = getinoquota(oip))
329 			return (error);
330 #endif
331 		if (error = bread(ITOV(oip), lbn, fs->lfs_bsize, NOCRED, &bp))
332 			return (error);
333 		oip->i_size = length;
334 		size = blksize(fs);				/* LFS */
335 		(void) vnode_pager_uncache(ITOV(oip));
336 		bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));
337 		allocbuf(bp, size);
338 #ifdef NOTLFS
339 		if (flags & IO_SYNC)				/* LFS */
340 			bwrite(bp);
341 		else
342 			bdwrite(bp);
343 #else
344 		lfs_bwrite(bp);
345 #endif
346 	}
347 	/*
348 	 * Update file and block pointers
349 	 * on disk before we start freeing blocks.
350 	 * If we crash before free'ing blocks below,
351 	 * the blocks will be returned to the free list.
352 	 * lastiblock values are also normalized to -1
353 	 * for calls to indirtrunc below.
354 	 */
355 	/* Will need to modify the segment usage information */	/* LFS */
356 	tip = *oip;
357 	tip.i_size = osize;
358 	for (level = TRIPLE; level >= SINGLE; level--)
359 		if (lastiblock[level] < 0) {
360 			oip->i_ib[level] = 0;
361 			lastiblock[level] = -1;
362 		}
363 	for (i = NDADDR - 1; i > lastblock; i--)
364 		oip->i_db[i] = 0;
365 	oip->i_flag |= ICHG|IUPD;
366 #ifdef NOTLFS
367 	vinvalbuf(ITOV(oip), (length > 0));
368 	allerror = ITIMES(oip, &time, &time);
369 #else
370 	/* Need lfs_vinvalbuf to get rid of invalid buffers in the cache */
371 	ITIMES(oip, &time, &time);
372 	allerror = 0;
373 #endif
374 
375 #ifdef NOTLFS
376 	/*
377 	 * Indirect blocks first.
378 	 */
379 	ip = &tip;
380 	for (level = TRIPLE; level >= SINGLE; level--) {
381 		bn = ip->i_ib[level];
382 		if (bn != 0) {
383 			error = indirtrunc(ip, bn, lastiblock[level], level,
384 				&count);
385 			if (error)
386 				allerror = error;
387 			blocksreleased += count;
388 			if (lastiblock[level] < 0) {
389 				ip->i_ib[level] = 0;
390 				blkfree(ip, bn, (off_t)fs->fs_bsize);
391 				blocksreleased += nblocks;
392 			}
393 		}
394 		if (lastiblock[level] >= 0)
395 			goto done;
396 	}
397 #else
398 	/* LFS -- not yet implemented.  Need to rewrite indirect blocks */
399 	panic("lfs_itrunc: not yet implemented");
400 #endif
401 
402 	/*
403 	 * All whole direct blocks or frags.
404 	 */
405 	for (i = NDADDR - 1; i > lastblock; i--) {
406 		register off_t bsize;
407 
408 		bn = ip->i_db[i];
409 		if (bn == 0)
410 			continue;
411 		ip->i_db[i] = 0;
412 		bsize = (off_t)blksize(fs);			/* LFS */
413 #ifdef NOTLFS
414 		blkfree(ip, bn, bsize);
415 #else
416 		/* LFS Update segment usage information */
417 #endif
418 		blocksreleased += btodb(bsize);
419 	}
420 	if (lastblock < 0)
421 		goto done;
422 
423 	/*
424 	 * Finally, look for a change in size of the
425 	 * last direct block; release any frags.
426 	 */
427 	bn = ip->i_db[lastblock];
428 	if (bn != 0) {
429 		off_t oldspace, newspace;
430 
431 		/*
432 		 * Calculate amount of space we're giving
433 		 * back as old block size minus new block size.
434 		 */
435 		oldspace = blksize(fs);				/* LFS */
436 		ip->i_size = length;
437 		newspace = blksize(fs);				/* LFS */
438 		if (newspace == 0)
439 			panic("lfs_itrunc: newspace");
440 		if (oldspace - newspace > 0) {
441 			/*
442 			 * Block number of space to be free'd is
443 			 * the old block # plus the number of frags
444 			 * required for the storage we're keeping.
445 			 */
446 			bn += numfrags(fs, newspace);
447 			blkfree(ip, bn, oldspace - newspace);
448 			blocksreleased += btodb(oldspace - newspace);
449 		}
450 	}
451 done:
452 /* BEGIN PARANOIA */
453 	for (level = SINGLE; level <= TRIPLE; level++)
454 		if (ip->i_ib[level] != oip->i_ib[level])
455 			panic("lfs_itrunc1");
456 	for (i = 0; i < NDADDR; i++)
457 		if (ip->i_db[i] != oip->i_db[i])
458 			panic("lfs_itrunc2");
459 /* END PARANOIA */
460 	oip->i_blocks -= blocksreleased;
461 	if (oip->i_blocks < 0)			/* sanity */
462 		oip->i_blocks = 0;
463 	oip->i_flag |= ICHG;
464 #ifdef QUOTA
465 	if (!getinoquota(oip))
466 		(void) chkdq(oip, -blocksreleased, NOCRED, 0);
467 #endif
468 	return (allerror);
469 }
470 
471 /*
472  * Release blocks associated with the inode ip and
473  * stored in the indirect block bn.  Blocks are free'd
474  * in LIFO order up to (but not including) lastbn.  If
475  * level is greater than SINGLE, the block is an indirect
476  * block and recursive calls to indirtrunc must be used to
477  * cleanse other indirect blocks.
478  *
479  * NB: triple indirect blocks are untested.
480  */
481 lfs_indirtrunc(ip, bn, lastbn, level, countp)
482 	register struct inode *ip;
483 	daddr_t bn, lastbn;
484 	int level;
485 	long *countp;
486 {
487 #ifdef NOTLFS
488 	register int i;
489 	struct buf *bp;
490 	register struct fs *fs = ip->i_fs;
491 	register daddr_t *bap;
492 	daddr_t *copy, nb, last;
493 	long blkcount, factor;
494 	int nblocks, blocksreleased = 0;
495 	int error, allerror = 0;
496 
497 	/*
498 	 * Calculate index in current block of last
499 	 * block to be kept.  -1 indicates the entire
500 	 * block so we need not calculate the index.
501 	 */
502 	factor = 1;
503 	for (i = SINGLE; i < level; i++)
504 		factor *= NINDIR(fs);
505 	last = lastbn;
506 	if (lastbn > 0)
507 		last /= factor;
508 	nblocks = btodb(fs->fs_bsize);
509 	/*
510 	 * Get buffer of block pointers, zero those
511 	 * entries corresponding to blocks to be free'd,
512 	 * and update on disk copy first.
513 	 */
514 	error = bread(ip->i_devvp, fsbtodb(fs, bn), (int)fs->fs_bsize,
515 		NOCRED, &bp);
516 	if (error) {
517 		brelse(bp);
518 		*countp = 0;
519 		return (error);
520 	}
521 	bap = bp->b_un.b_daddr;
522 	MALLOC(copy, daddr_t *, fs->fs_bsize, M_TEMP, M_WAITOK);
523 	bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->fs_bsize);
524 	bzero((caddr_t)&bap[last + 1],
525 	  (u_int)(NINDIR(fs) - (last + 1)) * sizeof (daddr_t));
526 	if (last == -1)
527 		bp->b_flags |= B_INVAL;
528 	error = bwrite(bp);
529 	if (error)
530 		allerror = error;
531 	bap = copy;
532 
533 	/*
534 	 * Recursively free totally unused blocks.
535 	 */
536 	for (i = NINDIR(fs) - 1; i > last; i--) {
537 		nb = bap[i];
538 		if (nb == 0)
539 			continue;
540 		if (level > SINGLE) {
541 			error = indirtrunc(ip, nb, (daddr_t)-1, level - 1,
542 				&blkcount);
543 			if (error)
544 				allerror = error;
545 			blocksreleased += blkcount;
546 		}
547 		blkfree(ip, nb, (off_t)fs->fs_bsize);
548 		blocksreleased += nblocks;
549 	}
550 
551 	/*
552 	 * Recursively free last partial block.
553 	 */
554 	if (level > SINGLE && lastbn >= 0) {
555 		last = lastbn % factor;
556 		nb = bap[i];
557 		if (nb != 0) {
558 			error = indirtrunc(ip, nb, last, level - 1, &blkcount);
559 			if (error)
560 				allerror = error;
561 			blocksreleased += blkcount;
562 		}
563 	}
564 	FREE(copy, M_TEMP);
565 	*countp = blocksreleased;
566 	return (allerror);
567 #else
568 	/* LFS IMPLEMENT -- lfs_indirtrunc */
569 	panic("lfs_indirtrunc not implemented");
570 #endif
571 }
572 #endif /* LOGFS */
573