xref: /original-bsd/sys/ufs/ffs/ufs_inode.c (revision 6c57d260)
1 /*	ufs_inode.c	4.5	81/04/28	*/
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 		prele(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 		prele(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 && (ip->i_mode&IFMT)!=IFMPC
245 			   && (ip->i_mode&IFMT)!=IFMPB)
246 				printf("iaddress > 2^24\n");
247 		}
248 		if(ip->i_flag&IACC)
249 			dp->di_atime = *ta;
250 		if(ip->i_flag&IUPD)
251 			dp->di_mtime = *tm;
252 		if(ip->i_flag&ICHG)
253 			dp->di_ctime = time;
254 		ip->i_flag &= ~(IUPD|IACC|ICHG);
255 		if (waitfor)
256 			bwrite(bp);
257 		else
258 			bdwrite(bp);
259 	}
260 }
261 
262 /*
263  * Free all the disk blocks associated
264  * with the specified inode structure.
265  * The blocks of the file are removed
266  * in reverse order. This FILO
267  * algorithm will tend to maintain
268  * a contiguous free list much longer
269  * than FIFO.
270  */
271 itrunc(ip)
272 register struct inode *ip;
273 {
274 	register i;
275 	dev_t dev;
276 	daddr_t bn;
277 	struct inode itmp;
278 
279 	if (ip->i_vfdcnt)
280 		panic("itrunc");
281 	i = ip->i_mode & IFMT;
282 	if (i!=IFREG && i!=IFDIR)
283 		return;
284 
285 	/*
286 	 * Clean inode on disk before freeing blocks
287 	 * to insure no duplicates if system crashes.
288 	 */
289 	itmp = *ip;
290 	itmp.i_size = 0;
291 	for (i = 0; i < NADDR; i++)
292 		itmp.i_un.i_addr[i] = 0;
293 	itmp.i_flag |= ICHG|IUPD;
294 	iupdat(&itmp, &time, &time, 1);
295 	ip->i_flag &= ~(IUPD|IACC|ICHG);
296 
297 	/*
298 	 * Now return blocks to free list... if machine
299 	 * crashes, they will be harmless MISSING blocks.
300 	 */
301 	dev = ip->i_dev;
302 	for(i=NADDR-1; i>=0; i--) {
303 		bn = ip->i_un.i_addr[i];
304 		if(bn == (daddr_t)0)
305 			continue;
306 		ip->i_un.i_addr[i] = (daddr_t)0;
307 		switch(i) {
308 
309 		default:
310 			free(dev, bn);
311 			break;
312 
313 		case NADDR-3:
314 			tloop(dev, bn, 0, 0);
315 			break;
316 
317 		case NADDR-2:
318 			tloop(dev, bn, 1, 0);
319 			break;
320 
321 		case NADDR-1:
322 			tloop(dev, bn, 1, 1);
323 		}
324 	}
325 	ip->i_size = 0;
326 	/*
327 	 * Inode was written and flags updated above.
328 	 * No need to modify flags here.
329 	 */
330 }
331 
332 tloop(dev, bn, f1, f2)
333 dev_t dev;
334 daddr_t bn;
335 {
336 	register i;
337 	register struct buf *bp;
338 	register daddr_t *bap;
339 	daddr_t nb;
340 
341 	bp = NULL;
342 	for(i=NINDIR-1; i>=0; i--) {
343 		if(bp == NULL) {
344 			bp = bread(dev, bn);
345 			if (bp->b_flags & B_ERROR) {
346 				brelse(bp);
347 				return;
348 			}
349 			bap = bp->b_un.b_daddr;
350 		}
351 		nb = bap[i];
352 		if(nb == (daddr_t)0)
353 			continue;
354 		if(f1) {
355 			brelse(bp);
356 			bp = NULL;
357 			tloop(dev, nb, f2, 0);
358 		} else
359 			free(dev, nb);
360 	}
361 	if(bp != NULL)
362 		brelse(bp);
363 	free(dev, bn);
364 }
365 
366 /*
367  * Make a new file.
368  */
369 struct inode *
370 maknode(mode)
371 {
372 	register struct inode *ip;
373 
374 	ip = ialloc(u.u_pdir->i_dev);
375 	if(ip == NULL) {
376 		iput(u.u_pdir);
377 		return(NULL);
378 	}
379 	ip->i_flag |= IACC|IUPD|ICHG;
380 	if((mode&IFMT) == 0)
381 		mode |= IFREG;
382 	ip->i_mode = mode & ~u.u_cmask;
383 	ip->i_nlink = 1;
384 	ip->i_uid = u.u_uid;
385 	ip->i_gid = u.u_gid;
386 
387 	/*
388 	 * Make sure inode goes to disk before directory entry.
389 	 */
390 	iupdat(ip, &time, &time, 1);
391 
392 	wdir(ip);
393 	return(ip);
394 }
395 
396 /*
397  * Write a directory entry with
398  * parameters left as side effects
399  * to a call to namei.
400  */
401 wdir(ip)
402 struct inode *ip;
403 {
404 
405 	u.u_dent.d_ino = ip->i_number;
406 	bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ);
407 	u.u_count = sizeof(struct direct);
408 	u.u_segflg = 1;
409 	u.u_base = (caddr_t)&u.u_dent;
410 	writei(u.u_pdir);
411 	iput(u.u_pdir);
412 }
413 
414 #ifdef plock
415 #undef plock
416 #endif
417 #ifdef prele
418 #undef prele
419 #endif
420 /*
421  * Lock an inode (should be called ilock).
422  * If its already locked,
423  * set the WANT bit and sleep.
424  */
425 plock(ip)
426 register struct inode *ip;
427 {
428 
429 	while(ip->i_flag&ILOCK) {
430 		ip->i_flag |= IWANT;
431 		sleep((caddr_t)ip, PINOD);
432 	}
433 	ip->i_flag |= ILOCK;
434 }
435 
436 /*
437  * Unlock an inode.
438  * If WANT bit is on,
439  * wakeup.
440  */
441 prele(ip)
442 register struct inode *ip;
443 {
444 
445 	ip->i_flag &= ~ILOCK;
446 	if(ip->i_flag&IWANT) {
447 		ip->i_flag &= ~IWANT;
448 		wakeup((caddr_t)ip);
449 	}
450 }
451