xref: /original-bsd/sys/ufs/lfs/lfs_inode.c (revision 42ef0c70)
1 /*	lfs_inode.c	4.9	82/02/27	*/
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/ino.h"
10 #include "../h/filsys.h"
11 #include "../h/conf.h"
12 #include "../h/buf.h"
13 #include "../h/inline.h"
14 
15 #define	INOHSZ	63
16 #define	INOHASH(dev,ino)	(((dev)+(ino))%INOHSZ)
17 short	inohash[INOHSZ];
18 short	ifreel;
19 
20 /*
21  * Initialize hash links for inodes
22  * and build inode free list.
23  */
24 ihinit()
25 {
26 	register int i;
27 	register struct inode *ip = inode;
28 
29 	ifreel = 0;
30 	for (i = 0; i < ninode-1; i++, ip++)
31 		ip->i_hlink = i+1;
32 	ip->i_hlink = -1;
33 	for (i = 0; i < INOHSZ; i++)
34 		inohash[i] = -1;
35 }
36 
37 /*
38  * Find an inode if it is incore.
39  * This is the equivalent, for inodes,
40  * of ``incore'' in bio.c or ``pfind'' in subr.c.
41  */
42 struct inode *
43 ifind(dev, ino)
44 	dev_t dev;
45 	ino_t ino;
46 {
47 	register struct inode *ip;
48 
49 	for (ip = &inode[inohash[INOHASH(dev,ino)]]; ip != &inode[-1];
50 	    ip = &inode[ip->i_hlink])
51 		if (ino==ip->i_number && dev==ip->i_dev)
52 			return (ip);
53 	return ((struct inode *)0);
54 }
55 
56 /*
57  * Look up an inode by device,inumber.
58  * If it is in core (in the inode structure),
59  * honor the locking protocol.
60  * If it is not in core, read it in from the
61  * specified device.
62  * If the inode is mounted on, perform
63  * the indicated indirection.
64  * In all cases, a pointer to a locked
65  * inode structure is returned.
66  *
67  * panic: no imt -- if the mounted file
68  *	system is not in the mount table.
69  *	"cannot happen"
70  */
71 struct inode *
72 iget(dev, ino)
73 	dev_t dev;
74 	ino_t ino;
75 {
76 	register struct inode *ip;
77 	register struct mount *mp;
78 	register struct buf *bp;
79 	register struct dinode *dp;
80 	register int slot;
81 
82 loop:
83 	slot = INOHASH(dev, ino);
84 	ip = &inode[inohash[slot]];
85 	while (ip != &inode[-1]) {
86 		if (ino == ip->i_number && dev == ip->i_dev) {
87 			if ((ip->i_flag&ILOCK) != 0) {
88 				ip->i_flag |= IWANT;
89 				sleep((caddr_t)ip, PINOD);
90 				goto loop;
91 			}
92 			if ((ip->i_flag&IMOUNT) != 0) {
93 				for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
94 				if (mp->m_inodp == ip) {
95 					dev = mp->m_dev;
96 					ino = ROOTINO;
97 					goto loop;
98 				}
99 				panic("no imt");
100 			}
101 			ip->i_count++;
102 			ip->i_flag |= ILOCK;
103 			return(ip);
104 		}
105 		ip = &inode[ip->i_hlink];
106 	}
107 	if (ifreel < 0) {
108 		tablefull("inode");
109 		u.u_error = ENFILE;
110 		return(NULL);
111 	}
112 	ip = &inode[ifreel];
113 	ifreel = ip->i_hlink;
114 	ip->i_hlink = inohash[slot];
115 	inohash[slot] = ip - inode;
116 	ip->i_dev = dev;
117 	ip->i_number = ino;
118 	ip->i_flag = ILOCK;
119 	ip->i_count++;
120 	ip->i_un.i_lastr = 0;
121 	bp = bread(dev, itod(ino));
122 	/*
123 	 * Check I/O errors
124 	 */
125 	if ((bp->b_flags&B_ERROR) != 0) {
126 		brelse(bp);
127 		iput(ip);
128 		return(NULL);
129 	}
130 	dp = bp->b_un.b_dino;
131 	dp += itoo(ino);
132 	iexpand(ip, dp);
133 	brelse(bp);
134 	return(ip);
135 }
136 
137 iexpand(ip, dp)
138 	register struct inode *ip;
139 	register struct dinode *dp;
140 {
141 	register char *p1, *p2;
142 	register int i;
143 
144 	ip->i_mode = dp->di_mode;
145 	ip->i_nlink = dp->di_nlink;
146 	ip->i_uid = dp->di_uid;
147 	ip->i_gid = dp->di_gid;
148 	ip->i_size = dp->di_size;
149 	p1 = (char *)ip->i_un.i_addr;
150 	p2 = (char *)dp->di_addr;
151 	for(i=0; i<NADDR; i++) {
152 		*p1++ = *p2++;
153 		*p1++ = *p2++;
154 		*p1++ = *p2++;
155 		*p1++ = 0;
156 	}
157 }
158 
159 /*
160  * Decrement reference count of
161  * an inode structure.
162  * On the last reference,
163  * write the inode out and if necessary,
164  * truncate and deallocate the file.
165  */
166 iput(ip)
167 	register struct inode *ip;
168 {
169 	register int i, x;
170 	register struct inode *jp;
171 
172 	if (ip->i_count == 1) {
173 		ip->i_flag |= ILOCK;
174 		if (ip->i_nlink <= 0) {
175 			itrunc(ip);
176 			ip->i_mode = 0;
177 			ip->i_flag |= IUPD|ICHG;
178 			ifree(ip->i_dev, ip->i_number);
179 		}
180 		IUPDAT(ip, &time, &time, 0);
181 		irele(ip);
182 		i = INOHASH(ip->i_dev, ip->i_number);
183 		x = ip - inode;
184 		if (inohash[i] == x) {
185 			inohash[i] = ip->i_hlink;
186 		} else {
187 			for (jp = &inode[inohash[i]]; jp != &inode[-1];
188 			    jp = &inode[jp->i_hlink])
189 				if (jp->i_hlink == x) {
190 					jp->i_hlink = ip->i_hlink;
191 					goto done;
192 				}
193 			panic("iput");
194 		}
195 done:
196 		ip->i_hlink = ifreel;
197 		ifreel = x;
198 		ip->i_flag = 0;
199 		ip->i_number = 0;
200 	} else
201 		irele(ip);
202 	ip->i_count--;
203 }
204 
205 /*
206  * Check accessed and update flags on
207  * an inode structure.
208  * If any is on, update the inode
209  * with the current time.
210  * If waitfor is given, then must insure
211  * i/o order so wait for write to complete.
212  */
213 iupdat(ip, ta, tm, waitfor)
214 	register struct inode *ip;
215 	time_t *ta, *tm;
216 	int waitfor;
217 {
218 	register struct buf *bp;
219 	struct dinode *dp;
220 	register char *p1, *p2;
221 	register int i;
222 
223 	if ((ip->i_flag&(IUPD|IACC|ICHG)) != 0) {
224 		if (getfs(ip->i_dev)->s_ronly)
225 			return;
226 		bp = bread(ip->i_dev, itod(ip->i_number));
227 		if (bp->b_flags & B_ERROR) {
228 			brelse(bp);
229 			return;
230 		}
231 		dp = bp->b_un.b_dino;
232 		dp += itoo(ip->i_number);
233 		dp->di_mode = ip->i_mode;
234 		dp->di_nlink = ip->i_nlink;
235 		dp->di_uid = ip->i_uid;
236 		dp->di_gid = ip->i_gid;
237 		dp->di_size = ip->i_size;
238 		p1 = (char *)dp->di_addr;
239 		p2 = (char *)ip->i_un.i_addr;
240 		for(i=0; i<NADDR; i++) {
241 			*p1++ = *p2++;
242 			*p1++ = *p2++;
243 			*p1++ = *p2++;
244 			if (*p2++ != 0)
245 				printf("iaddress > 2^24\n");
246 		}
247 		if (ip->i_flag&IACC)
248 			dp->di_atime = *ta;
249 		if (ip->i_flag&IUPD)
250 			dp->di_mtime = *tm;
251 		if (ip->i_flag&ICHG)
252 			dp->di_ctime = time;
253 		ip->i_flag &= ~(IUPD|IACC|ICHG);
254 		if (waitfor)
255 			bwrite(bp);
256 		else
257 			bdwrite(bp);
258 	}
259 }
260 
261 /*
262  * Free all the disk blocks associated
263  * with the specified inode structure.
264  * The blocks of the file are removed
265  * in reverse order. This FILO
266  * algorithm will tend to maintain
267  * a contiguous free list much longer
268  * than FIFO.
269  */
270 itrunc(ip)
271 	register struct inode *ip;
272 {
273 	register i;
274 	dev_t dev;
275 	daddr_t bn;
276 	struct inode itmp;
277 
278 	i = ip->i_mode & IFMT;
279 	if (i!=IFREG && i!=IFDIR && i!=IFLNK)
280 		return;
281 
282 	/*
283 	 * Clean inode on disk before freeing blocks
284 	 * to insure no duplicates if system crashes.
285 	 */
286 	itmp = *ip;
287 	itmp.i_size = 0;
288 	for (i = 0; i < NADDR; i++)
289 		itmp.i_un.i_addr[i] = 0;
290 	itmp.i_flag |= ICHG|IUPD;
291 	iupdat(&itmp, &time, &time, 1);
292 	ip->i_flag &= ~(IUPD|IACC|ICHG);
293 
294 	/*
295 	 * Now return blocks to free list... if machine
296 	 * crashes, they will be harmless MISSING blocks.
297 	 */
298 	dev = ip->i_dev;
299 	for(i=NADDR-1; i>=0; i--) {
300 		bn = ip->i_un.i_addr[i];
301 		if (bn == (daddr_t)0)
302 			continue;
303 		ip->i_un.i_addr[i] = (daddr_t)0;
304 		switch(i) {
305 
306 		default:
307 			free(dev, bn);
308 			break;
309 
310 		case NADDR-3:
311 			tloop(dev, bn, 0, 0);
312 			break;
313 
314 		case NADDR-2:
315 			tloop(dev, bn, 1, 0);
316 			break;
317 
318 		case NADDR-1:
319 			tloop(dev, bn, 1, 1);
320 		}
321 	}
322 	ip->i_size = 0;
323 	/*
324 	 * Inode was written and flags updated above.
325 	 * No need to modify flags here.
326 	 */
327 }
328 
329 tloop(dev, bn, f1, f2)
330 dev_t dev;
331 daddr_t bn;
332 {
333 	register i;
334 	register struct buf *bp;
335 	register daddr_t *bap;
336 	daddr_t nb;
337 
338 	bp = NULL;
339 	for(i=NINDIR-1; i>=0; i--) {
340 		if (bp == NULL) {
341 			bp = bread(dev, bn);
342 			if (bp->b_flags & B_ERROR) {
343 				brelse(bp);
344 				return;
345 			}
346 			bap = bp->b_un.b_daddr;
347 		}
348 		nb = bap[i];
349 		if (nb == (daddr_t)0)
350 			continue;
351 		if (f1) {
352 			brelse(bp);
353 			bp = NULL;
354 			tloop(dev, nb, f2, 0);
355 		} else
356 			free(dev, nb);
357 	}
358 	if (bp != NULL)
359 		brelse(bp);
360 	free(dev, bn);
361 }
362 
363 /*
364  * Make a new file.
365  */
366 struct inode *
367 maknode(mode)
368 {
369 	register struct inode *ip;
370 
371 	ip = ialloc(u.u_pdir->i_dev);
372 	if (ip == NULL) {
373 		iput(u.u_pdir);
374 		return(NULL);
375 	}
376 	ip->i_flag |= IACC|IUPD|ICHG;
377 	if ((mode&IFMT) == 0)
378 		mode |= IFREG;
379 	ip->i_mode = mode & ~u.u_cmask;
380 	ip->i_nlink = 1;
381 	ip->i_uid = u.u_uid;
382 	ip->i_gid = u.u_pdir->i_gid;
383 
384 	/*
385 	 * Make sure inode goes to disk before directory entry.
386 	 */
387 	iupdat(ip, &time, &time, 1);
388 
389 	wdir(ip);
390 	return(ip);
391 }
392 
393 /*
394  * Write a directory entry with
395  * parameters left as side effects
396  * to a call to namei.
397  */
398 wdir(ip)
399 	struct inode *ip;
400 {
401 
402 	u.u_dent.d_ino = ip->i_number;
403 	bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ);
404 	u.u_count = sizeof(struct direct);
405 	u.u_segflg = 1;
406 	u.u_base = (caddr_t)&u.u_dent;
407 	writei(u.u_pdir);
408 	iput(u.u_pdir);
409 }
410 
411 #ifdef ilock
412 #undef ilock
413 #endif
414 #ifdef irele
415 #undef irele
416 #endif
417 /*
418  * Lock an inode. If its already locked, set the WANT bit and sleep.
419  */
420 ilock(ip)
421 	register struct inode *ip;
422 {
423 
424 	while (ip->i_flag&ILOCK) {
425 		ip->i_flag |= IWANT;
426 		sleep((caddr_t)ip, PINOD);
427 	}
428 	ip->i_flag |= ILOCK;
429 }
430 
431 /*
432  * Unlock an inode.  If WANT bit is on, wakeup.
433  */
434 irele(ip)
435 	register struct inode *ip;
436 {
437 
438 	ip->i_flag &= ~ILOCK;
439 	if (ip->i_flag&IWANT) {
440 		ip->i_flag &= ~IWANT;
441 		wakeup((caddr_t)ip);
442 	}
443 }
444