xref: /csrg-svn/sys/ufs/ffs/ffs_inode.c (revision 7118)
1 /*	ffs_inode.c	4.11	82/06/07	*/
2 
3 /* merged into kernel:	@(#)iget.c 2.2 4/8/82 */
4 
5 #include "../h/param.h"
6 #include "../h/systm.h"
7 #include "../h/mount.h"
8 #include "../h/dir.h"
9 #include "../h/user.h"
10 #include "../h/inode.h"
11 #include "../h/fs.h"
12 #include "../h/conf.h"
13 #include "../h/buf.h"
14 #include "../h/inline.h"
15 
16 #define	INOHSZ	63
17 #define	INOHASH(dev,ino)	(((dev)+(ino))%INOHSZ)
18 short	inohash[INOHSZ];
19 short	ifreel;
20 
21 /*
22  * Initialize hash links for inodes
23  * and build inode free list.
24  */
25 ihinit()
26 {
27 	register int i;
28 	register struct inode *ip = inode;
29 
30 	ifreel = 0;
31 	for (i = 0; i < ninode-1; i++, ip++)
32 		ip->i_hlink = i+1;
33 	ip->i_hlink = -1;
34 	for (i = 0; i < INOHSZ; i++)
35 		inohash[i] = -1;
36 }
37 
38 /*
39  * Look up an inode by device,inumber.
40  * If it is in core (in the inode structure),
41  * honor the locking protocol.
42  * If it is not in core, read it in from the
43  * specified device.
44  * If the inode is mounted on, perform
45  * the indicated indirection.
46  * In all cases, a pointer to a locked
47  * inode structure is returned.
48  *
49  * panic: no imt -- if the mounted file
50  *	system is not in the mount table.
51  *	"cannot happen"
52  */
53 struct inode *
54 iget(dev, fs, ino)
55 	dev_t dev;
56 	register struct fs *fs;
57 	ino_t ino;
58 {
59 	register struct inode *ip;
60 	register struct mount *mp;
61 	register struct buf *bp;
62 	register struct dinode *dp;
63 	register int slot;
64 
65 loop:
66 	if (getfs(dev) != fs)
67 		panic("iget: bad fs");
68 	slot = INOHASH(dev, ino);
69 	ip = &inode[inohash[slot]];
70 	while (ip != &inode[-1]) {
71 		if (ino == ip->i_number && dev == ip->i_dev) {
72 			if ((ip->i_flag&ILOCK) != 0) {
73 				ip->i_flag |= IWANT;
74 				sleep((caddr_t)ip, PINOD);
75 				goto loop;
76 			}
77 			if ((ip->i_flag&IMOUNT) != 0) {
78 				for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
79 				if (mp->m_inodp == ip) {
80 					dev = mp->m_dev;
81 					fs = mp->m_bufp->b_un.b_fs;
82 					ino = ROOTINO;
83 					goto loop;
84 				}
85 				panic("no imt");
86 			}
87 			ip->i_count++;
88 			ip->i_flag |= ILOCK;
89 			return(ip);
90 		}
91 		ip = &inode[ip->i_hlink];
92 	}
93 	if (ifreel < 0) {
94 		tablefull("inode");
95 		u.u_error = ENFILE;
96 		return(NULL);
97 	}
98 	ip = &inode[ifreel];
99 	ifreel = ip->i_hlink;
100 	ip->i_hlink = inohash[slot];
101 	inohash[slot] = ip - inode;
102 	ip->i_dev = dev;
103 	ip->i_fs = fs;
104 	ip->i_number = ino;
105 	ip->i_flag = ILOCK;
106 	ip->i_count++;
107 	ip->i_lastr = 0;
108 	bp = bread(dev, fsbtodb(fs, itod(fs, ino)), fs->fs_bsize);
109 	/*
110 	 * Check I/O errors
111 	 */
112 	if ((bp->b_flags&B_ERROR) != 0) {
113 		brelse(bp);
114 		iput(ip);
115 		return(NULL);
116 	}
117 	dp = bp->b_un.b_dino;
118 	dp += itoo(fs, ino);
119 	ip->i_ic = dp->di_ic;
120 	brelse(bp);
121 	return (ip);
122 }
123 
124 /*
125  * Decrement reference count of
126  * an inode structure.
127  * On the last reference,
128  * write the inode out and if necessary,
129  * truncate and deallocate the file.
130  */
131 iput(ip)
132 	register struct inode *ip;
133 {
134 
135 	if ((ip->i_flag & ILOCK) == 0)
136 		panic("iput");
137 	iunlock(ip);
138 	irele(ip);
139 }
140 
141 irele(ip)
142 	register struct inode *ip;
143 {
144 	register int i, x;
145 	register struct inode *jp;
146 	int mode;
147 
148 	if (ip->i_flag & ILOCK)
149 		panic("irele");
150 	if (ip->i_count == 1) {
151 		ip->i_flag |= ILOCK;
152 		if (ip->i_nlink <= 0) {
153 			itrunc(ip);
154 			mode = ip->i_mode;
155 			ip->i_mode = 0;
156 			ip->i_flag |= IUPD|ICHG;
157 			ifree(ip, ip->i_number, mode);
158 		}
159 		IUPDAT(ip, &time, &time, 0);
160 		iunlock(ip);
161 		i = INOHASH(ip->i_dev, ip->i_number);
162 		x = ip - inode;
163 		if (inohash[i] == x) {
164 			inohash[i] = ip->i_hlink;
165 		} else {
166 			for (jp = &inode[inohash[i]]; jp != &inode[-1];
167 			    jp = &inode[jp->i_hlink])
168 				if (jp->i_hlink == x) {
169 					jp->i_hlink = ip->i_hlink;
170 					goto done;
171 				}
172 			panic("iput");
173 		}
174 done:
175 		ip->i_hlink = ifreel;
176 		ifreel = x;
177 		ip->i_flag = 0;
178 		ip->i_number = 0;
179 	}
180 	ip->i_count--;
181 }
182 
183 /*
184  * Check accessed and update flags on
185  * an inode structure.
186  * If any is on, update the inode
187  * with the current time.
188  * If waitfor is given, then must insure
189  * i/o order so wait for write to complete.
190  */
191 iupdat(ip, ta, tm, waitfor)
192 	register struct inode *ip;
193 	time_t *ta, *tm;
194 	int waitfor;
195 {
196 	register struct buf *bp;
197 	struct dinode *dp;
198 	register struct fs *fp;
199 
200 	fp = ip->i_fs;
201 	if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) {
202 		if (fp->fs_ronly)
203 			return;
204 		bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)),
205 			fp->fs_bsize);
206 		if (bp->b_flags & B_ERROR) {
207 			brelse(bp);
208 			return;
209 		}
210 		if (ip->i_flag&IACC)
211 			ip->i_atime = *ta;
212 		if (ip->i_flag&IUPD)
213 			ip->i_mtime = *tm;
214 		if (ip->i_flag&ICHG)
215 			ip->i_ctime = time;
216 		ip->i_flag &= ~(IUPD|IACC|ICHG);
217 		dp = bp->b_un.b_dino + itoo(fp, ip->i_number);
218 		dp->di_ic = ip->i_ic;
219 		if (waitfor)
220 			bwrite(bp);
221 		else
222 			bdwrite(bp);
223 	}
224 }
225 
226 /*
227  * Free all the disk blocks associated
228  * with the specified inode structure.
229  * The blocks of the file are removed
230  * in reverse order. This FILO
231  * algorithm will tend to maintain
232  * a contiguous free list much longer
233  * than FIFO.
234  */
235 itrunc(ip)
236 	register struct inode *ip;
237 {
238 	register i;
239 	dev_t dev;
240 	daddr_t bn;
241 	struct inode itmp;
242 	register struct fs *fs;
243 
244 	i = ip->i_mode & IFMT;
245 	if (i != IFREG && i != IFDIR && i != IFLNK)
246 		return;
247 	/*
248 	 * Clean inode on disk before freeing blocks
249 	 * to insure no duplicates if system crashes.
250 	 */
251 	itmp = *ip;
252 	itmp.i_size = 0;
253 	for (i = 0; i < NDADDR; i++)
254 		itmp.i_db[i] = 0;
255 	for (i = 0; i < NIADDR; i++)
256 		itmp.i_ib[i] = 0;
257 	itmp.i_flag |= ICHG|IUPD;
258 	iupdat(&itmp, &time, &time, 1);
259 	ip->i_flag &= ~(IUPD|IACC|ICHG);
260 
261 	/*
262 	 * Now return blocks to free list... if machine
263 	 * crashes, they will be harmless MISSING blocks.
264 	 */
265 	dev = ip->i_dev;
266 	fs = ip->i_fs;
267 	/*
268 	 * release double indirect block first
269 	 */
270 	bn = ip->i_ib[NIADDR-1];
271 	if (bn != (daddr_t)0) {
272 		ip->i_ib[NIADDR - 1] = (daddr_t)0;
273 		tloop(ip, bn, 1);
274 	}
275 	/*
276 	 * release single indirect blocks second
277 	 */
278 	for (i = NIADDR - 2; i >= 0; i--) {
279 		bn = ip->i_ib[i];
280 		if (bn != (daddr_t)0) {
281 			ip->i_ib[i] = (daddr_t)0;
282 			tloop(ip, bn, 0);
283 		}
284 	}
285 	/*
286 	 * finally release direct blocks
287 	 */
288 	for (i = NDADDR - 1; i>=0; i--) {
289 		bn = ip->i_db[i];
290 		if (bn == (daddr_t)0)
291 			continue;
292 		ip->i_db[i] = (daddr_t)0;
293 		fre(ip, bn, (off_t)blksize(fs, ip, i));
294 	}
295 	ip->i_size = 0;
296 	/*
297 	 * Inode was written and flags updated above.
298 	 * No need to modify flags here.
299 	 */
300 }
301 
302 tloop(ip, bn, indflg)
303 	register struct inode *ip;
304 	daddr_t bn;
305 	int indflg;
306 {
307 	register i;
308 	register struct buf *bp;
309 	register daddr_t *bap;
310 	register struct fs *fs;
311 	daddr_t nb;
312 
313 	bp = NULL;
314 	fs = ip->i_fs;
315 	for (i = NINDIR(fs) - 1; i >= 0; i--) {
316 		if (bp == NULL) {
317 			bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize);
318 			if (bp->b_flags & B_ERROR) {
319 				brelse(bp);
320 				return;
321 			}
322 			bap = bp->b_un.b_daddr;
323 		}
324 		nb = bap[i];
325 		if (nb == (daddr_t)0)
326 			continue;
327 		if (indflg)
328 			tloop(ip, nb, 0);
329 		else
330 			fre(ip, nb, fs->fs_bsize);
331 	}
332 	if (bp != NULL)
333 		brelse(bp);
334 	fre(ip, bn, fs->fs_bsize);
335 }
336 
337 /*
338  * Make a new file.
339  */
340 struct inode *
341 maknode(mode)
342 	int mode;
343 {
344 	register struct inode *ip;
345 	ino_t ipref;
346 
347 	if ((mode & IFMT) == IFDIR)
348 		ipref = dirpref(u.u_pdir->i_fs);
349 	else
350 		ipref = u.u_pdir->i_number;
351 	ip = ialloc(u.u_pdir, ipref, mode);
352 	if (ip == NULL) {
353 		iput(u.u_pdir);
354 		return(NULL);
355 	}
356 	ip->i_flag |= IACC|IUPD|ICHG;
357 	if ((mode & IFMT) == 0)
358 		mode |= IFREG;
359 	ip->i_mode = mode & ~u.u_cmask;
360 	ip->i_nlink = 1;
361 	ip->i_uid = u.u_uid;
362 	ip->i_gid = u.u_pdir->i_gid;
363 
364 	/*
365 	 * Make sure inode goes to disk before directory entry.
366 	 */
367 	iupdat(ip, &time, &time, 1);
368 	wdir(ip);
369 	if (u.u_error) {
370 		/*
371 		 * write error occurred trying to update directory
372 		 * so must deallocate the inode
373 		 */
374 		ip->i_nlink = 0;
375 		ip->i_flag |= ICHG;
376 		iput(ip);
377 		return(NULL);
378 	}
379 	return(ip);
380 }
381 
382 /*
383  * Write a directory entry with
384  * parameters left as side effects
385  * to a call to namei.
386  */
387 wdir(ip)
388 	struct inode *ip;
389 {
390 	register struct direct *dp, *ndp;
391 	struct fs *fs;
392 	struct buf *bp;
393 	int lbn, bn, base;
394 	int loc, dsize, spccnt, newsize;
395 	char *dirbuf;
396 
397 	u.u_dent.d_ino = ip->i_number;
398 	u.u_segflg = 1;
399 	newsize = DIRSIZ(&u.u_dent);
400 	/*
401 	 * if u.u_count == 0, a new directory block must be allocated.
402 	 */
403 	if (u.u_count == 0) {
404 		u.u_dent.d_reclen = DIRBLKSIZ;
405 		u.u_count = newsize;
406 		u.u_base = (caddr_t)&u.u_dent;
407 		writei(u.u_pdir);
408 		iput(u.u_pdir);
409 		return;
410 	}
411 	/*
412 	 * must read in an existing directory block
413 	 * to prepare to place the new entry into it.
414 	 */
415 	fs = u.u_pdir->i_fs;
416 	lbn = lblkno(fs, u.u_offset);
417 	base = blkoff(fs, u.u_offset);
418 	bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count));
419 	if (u.u_offset + u.u_count > u.u_pdir->i_size)
420 		u.u_pdir->i_size = u.u_offset + u.u_count;
421 	bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn));
422 	if (bp->b_flags & B_ERROR) {
423 		brelse(bp);
424 		return;
425 	}
426 	dirbuf = bp->b_un.b_addr + base;
427 	dp = (struct direct *)dirbuf;
428 	dsize = DIRSIZ(dp);
429 	spccnt = dp->d_reclen - dsize;
430 	/*
431 	 * if there is insufficient room to make an entry at this point
432 	 * namei insures that compacting from u.u_offset for u.u_count
433 	 * bytes will provide the necessary space.
434 	 */
435 	for (loc = dp->d_reclen; loc < u.u_count; ) {
436 		ndp = (struct direct *)(dirbuf + loc);
437 		if (dp->d_ino == 0) {
438 			spccnt += dsize;
439 		} else {
440 			dp->d_reclen = dsize;
441 			dp = (struct direct *)((char *)dp + dsize);
442 		}
443 		dsize = DIRSIZ(ndp);
444 		spccnt += ndp->d_reclen - dsize;
445 		loc += ndp->d_reclen;
446 		bcopy(ndp, dp, dsize);
447 	}
448 	/*
449 	 * Update the pointer fields in the previous entry (if any),
450 	 * copy in the new entry, and write out the block.
451 	 */
452 	if (dp->d_ino == 0) {
453 		if (spccnt + dsize < newsize)
454 			panic("wdir: compact failed");
455 		u.u_dent.d_reclen = spccnt + dsize;
456 	} else {
457 		if (spccnt < newsize)
458 			panic("wdir: compact failed");
459 		u.u_dent.d_reclen = spccnt;
460 		dp->d_reclen = dsize;
461 		dp = (struct direct *)((char *)dp + dsize);
462 	}
463 	bcopy(&u.u_dent, dp, newsize);
464 	bwrite(bp);
465 	u.u_pdir->i_flag |= IUPD|ICHG;
466 	iput(u.u_pdir);
467 }
468 
469 #ifdef ilock
470 #undef ilock
471 #endif
472 #ifdef iunlock
473 #undef iunlock
474 #endif
475 /*
476  * Lock an inode. If its already locked, set the WANT bit and sleep.
477  */
478 ilock(ip)
479 	register struct inode *ip;
480 {
481 
482 	while (ip->i_flag&ILOCK) {
483 		ip->i_flag |= IWANT;
484 		sleep((caddr_t)ip, PINOD);
485 	}
486 	ip->i_flag |= ILOCK;
487 }
488 
489 /*
490  * Unlock an inode.  If WANT bit is on, wakeup.
491  */
492 iunlock(ip)
493 	register struct inode *ip;
494 {
495 
496 	ip->i_flag &= ~ILOCK;
497 	if (ip->i_flag&IWANT) {
498 		ip->i_flag &= ~IWANT;
499 		wakeup((caddr_t)ip);
500 	}
501 }
502