xref: /original-bsd/sys/ufs/lfs/lfs_inode.c (revision 9a96b58b)
1 /*	lfs_inode.c	4.10	82/04/19	*/
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 	register int i, x;
135 	register struct inode *jp;
136 	int mode;
137 
138 	if (ip->i_count == 1) {
139 		ip->i_flag |= ILOCK;
140 		if (ip->i_nlink <= 0) {
141 			itrunc(ip);
142 			mode = ip->i_mode;
143 			ip->i_mode = 0;
144 			ip->i_flag |= IUPD|ICHG;
145 			ifree(ip, ip->i_number, mode);
146 		}
147 		IUPDAT(ip, &time, &time, 0);
148 		irele(ip);
149 		i = INOHASH(ip->i_dev, ip->i_number);
150 		x = ip - inode;
151 		if (inohash[i] == x) {
152 			inohash[i] = ip->i_hlink;
153 		} else {
154 			for (jp = &inode[inohash[i]]; jp != &inode[-1];
155 			    jp = &inode[jp->i_hlink])
156 				if (jp->i_hlink == x) {
157 					jp->i_hlink = ip->i_hlink;
158 					goto done;
159 				}
160 			panic("iput");
161 		}
162 done:
163 		ip->i_hlink = ifreel;
164 		ifreel = x;
165 		ip->i_flag = 0;
166 		ip->i_number = 0;
167 	} else
168 		irele(ip);
169 	ip->i_count--;
170 }
171 
172 /*
173  * Check accessed and update flags on
174  * an inode structure.
175  * If any is on, update the inode
176  * with the current time.
177  * If waitfor is given, then must insure
178  * i/o order so wait for write to complete.
179  */
180 iupdat(ip, ta, tm, waitfor)
181 	register struct inode *ip;
182 	time_t *ta, *tm;
183 	int waitfor;
184 {
185 	register struct buf *bp;
186 	struct dinode *dp;
187 	register struct fs *fp;
188 
189 	fp = ip->i_fs;
190 	if ((ip->i_flag & (IUPD|IACC|ICHG)) != 0) {
191 		if (fp->fs_ronly)
192 			return;
193 		bp = bread(ip->i_dev, fsbtodb(fp, itod(fp, ip->i_number)),
194 			fp->fs_bsize);
195 		if (bp->b_flags & B_ERROR) {
196 			brelse(bp);
197 			return;
198 		}
199 		if (ip->i_flag&IACC)
200 			ip->i_atime = *ta;
201 		if (ip->i_flag&IUPD)
202 			ip->i_mtime = *tm;
203 		if (ip->i_flag&ICHG)
204 			ip->i_ctime = time;
205 		ip->i_flag &= ~(IUPD|IACC|ICHG);
206 		dp = bp->b_un.b_dino + itoo(fp, ip->i_number);
207 		dp->di_ic = ip->i_ic;
208 		if (waitfor)
209 			bwrite(bp);
210 		else
211 			bdwrite(bp);
212 	}
213 }
214 
215 /*
216  * Free all the disk blocks associated
217  * with the specified inode structure.
218  * The blocks of the file are removed
219  * in reverse order. This FILO
220  * algorithm will tend to maintain
221  * a contiguous free list much longer
222  * than FIFO.
223  */
224 itrunc(ip)
225 	register struct inode *ip;
226 {
227 	register i;
228 	dev_t dev;
229 	daddr_t bn;
230 	struct inode itmp;
231 	register struct fs *fs;
232 
233 	i = ip->i_mode & IFMT;
234 	if (i != IFREG && i != IFDIR && i != IFLNK)
235 		return;
236 	/*
237 	 * Clean inode on disk before freeing blocks
238 	 * to insure no duplicates if system crashes.
239 	 */
240 	itmp = *ip;
241 	itmp.i_size = 0;
242 	for (i = 0; i < NDADDR; i++)
243 		itmp.i_db[i] = 0;
244 	for (i = 0; i < NIADDR; i++)
245 		itmp.i_ib[i] = 0;
246 	itmp.i_flag |= ICHG|IUPD;
247 	iupdat(&itmp, &time, &time, 1);
248 	ip->i_flag &= ~(IUPD|IACC|ICHG);
249 
250 	/*
251 	 * Now return blocks to free list... if machine
252 	 * crashes, they will be harmless MISSING blocks.
253 	 */
254 	dev = ip->i_dev;
255 	fs = ip->i_fs;
256 	/*
257 	 * release double indirect block first
258 	 */
259 	bn = ip->i_ib[NIADDR-1];
260 	if (bn != (daddr_t)0) {
261 		ip->i_ib[NIADDR - 1] = (daddr_t)0;
262 		tloop(ip, bn, 1);
263 	}
264 	/*
265 	 * release single indirect blocks second
266 	 */
267 	for (i = NIADDR - 2; i >= 0; i--) {
268 		bn = ip->i_ib[i];
269 		if (bn != (daddr_t)0) {
270 			ip->i_ib[i] = (daddr_t)0;
271 			tloop(ip, bn, 0);
272 		}
273 	}
274 	/*
275 	 * finally release direct blocks
276 	 */
277 	for (i = NDADDR - 1; i>=0; i--) {
278 		bn = ip->i_db[i];
279 		if (bn == (daddr_t)0)
280 			continue;
281 		ip->i_db[i] = (daddr_t)0;
282 		fre(ip, bn, (off_t)blksize(fs, ip, i));
283 	}
284 	ip->i_size = 0;
285 	/*
286 	 * Inode was written and flags updated above.
287 	 * No need to modify flags here.
288 	 */
289 }
290 
291 tloop(ip, bn, indflg)
292 	register struct inode *ip;
293 	daddr_t bn;
294 	int indflg;
295 {
296 	register i;
297 	register struct buf *bp;
298 	register daddr_t *bap;
299 	register struct fs *fs;
300 	daddr_t nb;
301 
302 	bp = NULL;
303 	fs = ip->i_fs;
304 	for (i = NINDIR(fs) - 1; i >= 0; i--) {
305 		if (bp == NULL) {
306 			bp = bread(ip->i_dev, fsbtodb(fs, bn), fs->fs_bsize);
307 			if (bp->b_flags & B_ERROR) {
308 				brelse(bp);
309 				return;
310 			}
311 			bap = bp->b_un.b_daddr;
312 		}
313 		nb = bap[i];
314 		if (nb == (daddr_t)0)
315 			continue;
316 		if (indflg)
317 			tloop(ip, nb, 0);
318 		else
319 			fre(ip, nb, fs->fs_bsize);
320 	}
321 	if (bp != NULL)
322 		brelse(bp);
323 	fre(ip, bn, fs->fs_bsize);
324 }
325 
326 /*
327  * Make a new file.
328  */
329 struct inode *
330 maknode(mode)
331 	int mode;
332 {
333 	register struct inode *ip;
334 	ino_t ipref;
335 
336 	if ((mode & IFMT) == IFDIR)
337 		ipref = dirpref(u.u_pdir->i_fs);
338 	else
339 		ipref = u.u_pdir->i_number;
340 	ip = ialloc(u.u_pdir, ipref, mode);
341 	if (ip == NULL) {
342 		iput(u.u_pdir);
343 		return(NULL);
344 	}
345 	ip->i_flag |= IACC|IUPD|ICHG;
346 	if ((mode & IFMT) == 0)
347 		mode |= IFREG;
348 	ip->i_mode = mode & ~u.u_cmask;
349 	ip->i_nlink = 1;
350 	ip->i_uid = u.u_uid;
351 	ip->i_gid = u.u_pdir->i_gid;
352 
353 	/*
354 	 * Make sure inode goes to disk before directory entry.
355 	 */
356 	iupdat(ip, &time, &time, 1);
357 	wdir(ip);
358 	if (u.u_error) {
359 		/*
360 		 * write error occurred trying to update directory
361 		 * so must deallocate the inode
362 		 */
363 		ip->i_nlink = 0;
364 		ip->i_flag |= ICHG;
365 		iput(ip);
366 		return(NULL);
367 	}
368 	return(ip);
369 }
370 
371 /*
372  * Write a directory entry with
373  * parameters left as side effects
374  * to a call to namei.
375  */
376 wdir(ip)
377 	struct inode *ip;
378 {
379 	register struct direct *dp, *ndp;
380 	struct fs *fs;
381 	struct buf *bp;
382 	int lbn, bn, base;
383 	int loc, dsize, spccnt, newsize;
384 	char *dirbuf;
385 
386 	u.u_dent.d_ino = ip->i_number;
387 	u.u_segflg = 1;
388 	newsize = DIRSIZ(&u.u_dent);
389 	/*
390 	 * if u.u_count == 0, a new directory block must be allocated.
391 	 */
392 	if (u.u_count == 0) {
393 		u.u_dent.d_reclen = DIRBLKSIZ;
394 		u.u_count = newsize;
395 		u.u_base = (caddr_t)&u.u_dent;
396 		writei(u.u_pdir);
397 		iput(u.u_pdir);
398 		return;
399 	}
400 	/*
401 	 * must read in an existing directory block
402 	 * to prepare to place the new entry into it.
403 	 */
404 	fs = u.u_pdir->i_fs;
405 	lbn = lblkno(fs, u.u_offset);
406 	base = blkoff(fs, u.u_offset);
407 	bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count));
408 	if (u.u_offset + u.u_count > u.u_pdir->i_size)
409 		u.u_pdir->i_size = u.u_offset + u.u_count;
410 	bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn));
411 	if (bp->b_flags & B_ERROR) {
412 		brelse(bp);
413 		return;
414 	}
415 	dirbuf = bp->b_un.b_addr + base;
416 	dp = (struct direct *)dirbuf;
417 	dsize = DIRSIZ(dp);
418 	spccnt = dp->d_reclen - dsize;
419 	/*
420 	 * if there is insufficient room to make an entry at this point
421 	 * namei insures that compacting from u.u_offset for u.u_count
422 	 * bytes will provide the necessary space.
423 	 */
424 	for (loc = dp->d_reclen; loc < u.u_count; ) {
425 		ndp = (struct direct *)(dirbuf + loc);
426 		if (dp->d_ino == 0) {
427 			spccnt += dsize;
428 		} else {
429 			dp->d_reclen = dsize;
430 			dp = (struct direct *)((char *)dp + dsize);
431 		}
432 		dsize = DIRSIZ(ndp);
433 		spccnt += ndp->d_reclen - dsize;
434 		loc += ndp->d_reclen;
435 		bcopy(ndp, dp, dsize);
436 	}
437 	/*
438 	 * Update the pointer fields in the previous entry (if any),
439 	 * copy in the new entry, and write out the block.
440 	 */
441 	if (dp->d_ino == 0) {
442 		if (spccnt + dsize < newsize)
443 			panic("wdir: compact failed");
444 		u.u_dent.d_reclen = spccnt + dsize;
445 	} else {
446 		if (spccnt < newsize)
447 			panic("wdir: compact failed");
448 		u.u_dent.d_reclen = spccnt;
449 		dp->d_reclen = dsize;
450 		dp = (struct direct *)((char *)dp + dsize);
451 	}
452 	bcopy(&u.u_dent, dp, newsize);
453 	bwrite(bp);
454 	u.u_pdir->i_flag |= IUPD|ICHG;
455 	iput(u.u_pdir);
456 }
457 
458 #ifdef ilock
459 #undef ilock
460 #endif
461 #ifdef irele
462 #undef irele
463 #endif
464 /*
465  * Lock an inode. If its already locked, set the WANT bit and sleep.
466  */
467 ilock(ip)
468 	register struct inode *ip;
469 {
470 
471 	while (ip->i_flag&ILOCK) {
472 		ip->i_flag |= IWANT;
473 		sleep((caddr_t)ip, PINOD);
474 	}
475 	ip->i_flag |= ILOCK;
476 }
477 
478 /*
479  * Unlock an inode.  If WANT bit is on, wakeup.
480  */
481 irele(ip)
482 	register struct inode *ip;
483 {
484 
485 	ip->i_flag &= ~ILOCK;
486 	if (ip->i_flag&IWANT) {
487 		ip->i_flag &= ~IWANT;
488 		wakeup((caddr_t)ip);
489 	}
490 }
491