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