xref: /csrg-svn/sys/ufs/ffs/ffs_inode.c (revision 2737)
1 /*	ffs_inode.c	4.2	02/26/81	*/
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  * printf warning: no inodes -- if the inode
68  *	structure is full
69  * panic: no imt -- if the mounted file
70  *	system is not in the mount table.
71  *	"cannot happen"
72  */
73 struct inode *
74 iget(dev, ino)
75 dev_t dev;
76 ino_t ino;
77 {
78 	register struct inode *ip;
79 	register struct mount *mp;
80 	register struct buf *bp;
81 	register struct dinode *dp;
82 	register int slot;
83 
84 loop:
85 	slot = INOHASH(dev, ino);
86 	ip = &inode[inohash[slot]];
87 	while (ip != &inode[-1]) {
88 		if(ino == ip->i_number && dev == ip->i_dev) {
89 			if((ip->i_flag&ILOCK) != 0) {
90 				ip->i_flag |= IWANT;
91 				sleep((caddr_t)ip, PINOD);
92 				goto loop;
93 			}
94 			if((ip->i_flag&IMOUNT) != 0) {
95 				for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
96 				if(mp->m_inodp == ip) {
97 					dev = mp->m_dev;
98 					ino = ROOTINO;
99 					goto loop;
100 				}
101 				panic("no imt");
102 			}
103 			ip->i_count++;
104 			ip->i_flag |= ILOCK;
105 			return(ip);
106 		}
107 		ip = &inode[ip->i_hlink];
108 	}
109 	if(ifreel < 0) {
110 		printf("Inode table overflow\n");
111 		u.u_error = ENFILE;
112 		return(NULL);
113 	}
114 	ip = &inode[ifreel];
115 	ifreel = ip->i_hlink;
116 	ip->i_hlink = inohash[slot];
117 	inohash[slot] = ip - inode;
118 	ip->i_dev = dev;
119 	ip->i_number = ino;
120 	ip->i_flag = ILOCK;
121 	ip->i_count++;
122 	ip->i_un.i_lastr = 0;
123 	bp = bread(dev, itod(ino));
124 	/*
125 	 * Check I/O errors
126 	 */
127 	if((bp->b_flags&B_ERROR) != 0) {
128 		brelse(bp);
129 		iput(ip);
130 		return(NULL);
131 	}
132 	dp = bp->b_un.b_dino;
133 	dp += itoo(ino);
134 	iexpand(ip, dp);
135 	brelse(bp);
136 	return(ip);
137 }
138 
139 iexpand(ip, dp)
140 register struct inode *ip;
141 register struct dinode *dp;
142 {
143 	register char *p1, *p2;
144 	register int i;
145 
146 	ip->i_mode = dp->di_mode;
147 	ip->i_nlink = dp->di_nlink;
148 	ip->i_uid = dp->di_uid;
149 	ip->i_gid = dp->di_gid;
150 	ip->i_size = dp->di_size;
151 	p1 = (char *)ip->i_un.i_addr;
152 	p2 = (char *)dp->di_addr;
153 	for(i=0; i<NADDR; i++) {
154 		*p1++ = *p2++;
155 		*p1++ = *p2++;
156 		*p1++ = *p2++;
157 		*p1++ = 0;
158 	}
159 }
160 
161 /*
162  * Decrement reference count of
163  * an inode structure.
164  * On the last reference,
165  * write the inode out and if necessary,
166  * truncate and deallocate the file.
167  */
168 iput(ip)
169 register struct inode *ip;
170 {
171 	register int i, x;
172 	register struct inode *jp;
173 
174 	if(ip->i_count == 1) {
175 		ip->i_flag |= ILOCK;
176 		if(ip->i_nlink <= 0) {
177 			itrunc(ip);
178 			ip->i_mode = 0;
179 			ip->i_flag |= IUPD|ICHG;
180 			ifree(ip->i_dev, ip->i_number);
181 		}
182 		IUPDAT(ip, &time, &time, 0);
183 		prele(ip);
184 		i = INOHASH(ip->i_dev, ip->i_number);
185 		x = ip - inode;
186 		if (inohash[i] == x) {
187 			inohash[i] = ip->i_hlink;
188 		} else {
189 			for (jp = &inode[inohash[i]]; jp != &inode[-1];
190 			    jp = &inode[jp->i_hlink])
191 				if (jp->i_hlink == x) {
192 					jp->i_hlink = ip->i_hlink;
193 					goto done;
194 				}
195 			panic("iput");
196 		}
197 done:
198 		ip->i_hlink = ifreel;
199 		ifreel = x;
200 		ip->i_flag = 0;
201 		ip->i_number = 0;
202 	} else
203 		prele(ip);
204 	ip->i_count--;
205 }
206 
207 /*
208  * Check accessed and update flags on
209  * an inode structure.
210  * If any is on, update the inode
211  * with the current time.
212  * If waitfor is given, then must insure
213  * i/o order so wait for write to complete.
214  */
215 iupdat(ip, ta, tm, waitfor)
216 register struct inode *ip;
217 time_t *ta, *tm;
218 int waitfor;
219 {
220 	register struct buf *bp;
221 	struct dinode *dp;
222 	register char *p1, *p2;
223 	register int i;
224 
225 	if((ip->i_flag&(IUPD|IACC|ICHG)) != 0) {
226 		if(getfs(ip->i_dev)->s_ronly)
227 			return;
228 		bp = bread(ip->i_dev, itod(ip->i_number));
229 		if (bp->b_flags & B_ERROR) {
230 			brelse(bp);
231 			return;
232 		}
233 		dp = bp->b_un.b_dino;
234 		dp += itoo(ip->i_number);
235 		dp->di_mode = ip->i_mode;
236 		dp->di_nlink = ip->i_nlink;
237 		dp->di_uid = ip->i_uid;
238 		dp->di_gid = ip->i_gid;
239 		dp->di_size = ip->i_size;
240 		p1 = (char *)dp->di_addr;
241 		p2 = (char *)ip->i_un.i_addr;
242 		for(i=0; i<NADDR; i++) {
243 			*p1++ = *p2++;
244 			*p1++ = *p2++;
245 			*p1++ = *p2++;
246 			if(*p2++ != 0 && (ip->i_mode&IFMT)!=IFMPC
247 			   && (ip->i_mode&IFMT)!=IFMPB)
248 				printf("iaddress > 2^24\n");
249 		}
250 		if(ip->i_flag&IACC)
251 			dp->di_atime = *ta;
252 		if(ip->i_flag&IUPD)
253 			dp->di_mtime = *tm;
254 		if(ip->i_flag&ICHG)
255 			dp->di_ctime = time;
256 		ip->i_flag &= ~(IUPD|IACC|ICHG);
257 		if (waitfor)
258 			bwrite(bp);
259 		else
260 			bdwrite(bp);
261 	}
262 }
263 
264 /*
265  * Free all the disk blocks associated
266  * with the specified inode structure.
267  * The blocks of the file are removed
268  * in reverse order. This FILO
269  * algorithm will tend to maintain
270  * a contiguous free list much longer
271  * than FIFO.
272  */
273 itrunc(ip)
274 register struct inode *ip;
275 {
276 	register i;
277 	dev_t dev;
278 	daddr_t bn;
279 	struct inode itmp;
280 
281 	if (ip->i_vfdcnt)
282 		panic("itrunc");
283 	i = ip->i_mode & IFMT;
284 	if (i!=IFREG && i!=IFDIR)
285 		return;
286 
287 	/*
288 	 * Clean inode on disk before freeing blocks
289 	 * to insure no duplicates if system crashes.
290 	 */
291 	itmp = *ip;
292 	itmp.i_size = 0;
293 	for (i = 0; i < NADDR; i++)
294 		itmp.i_un.i_addr[i] = 0;
295 	itmp.i_flag |= ICHG|IUPD;
296 	iupdat(&itmp, &time, &time, 1);
297 	ip->i_flag &= ~(IUPD|IACC|ICHG);
298 
299 	/*
300 	 * Now return blocks to free list... if machine
301 	 * crashes, they will be harmless MISSING blocks.
302 	 */
303 	dev = ip->i_dev;
304 	for(i=NADDR-1; i>=0; i--) {
305 		bn = ip->i_un.i_addr[i];
306 		if(bn == (daddr_t)0)
307 			continue;
308 		ip->i_un.i_addr[i] = (daddr_t)0;
309 		switch(i) {
310 
311 		default:
312 			free(dev, bn);
313 			break;
314 
315 		case NADDR-3:
316 			tloop(dev, bn, 0, 0);
317 			break;
318 
319 		case NADDR-2:
320 			tloop(dev, bn, 1, 0);
321 			break;
322 
323 		case NADDR-1:
324 			tloop(dev, bn, 1, 1);
325 		}
326 	}
327 	ip->i_size = 0;
328 	/*
329 	 * Inode was written and flags updated above.
330 	 * No need to modify flags here.
331 	 */
332 }
333 
334 tloop(dev, bn, f1, f2)
335 dev_t dev;
336 daddr_t bn;
337 {
338 	register i;
339 	register struct buf *bp;
340 	register daddr_t *bap;
341 	daddr_t nb;
342 
343 	bp = NULL;
344 	for(i=NINDIR-1; i>=0; i--) {
345 		if(bp == NULL) {
346 			bp = bread(dev, bn);
347 			if (bp->b_flags & B_ERROR) {
348 				brelse(bp);
349 				return;
350 			}
351 			bap = bp->b_un.b_daddr;
352 		}
353 		nb = bap[i];
354 		if(nb == (daddr_t)0)
355 			continue;
356 		if(f1) {
357 			brelse(bp);
358 			bp = NULL;
359 			tloop(dev, nb, f2, 0);
360 		} else
361 			free(dev, nb);
362 	}
363 	if(bp != NULL)
364 		brelse(bp);
365 	free(dev, bn);
366 }
367 
368 /*
369  * Make a new file.
370  */
371 struct inode *
372 maknode(mode)
373 {
374 	register struct inode *ip;
375 
376 	ip = ialloc(u.u_pdir->i_dev);
377 	if(ip == NULL) {
378 		iput(u.u_pdir);
379 		return(NULL);
380 	}
381 	ip->i_flag |= IACC|IUPD|ICHG;
382 	if((mode&IFMT) == 0)
383 		mode |= IFREG;
384 	ip->i_mode = mode & ~u.u_cmask;
385 	ip->i_nlink = 1;
386 	ip->i_uid = u.u_uid;
387 	ip->i_gid = u.u_gid;
388 
389 	/*
390 	 * Make sure inode goes to disk before directory entry.
391 	 */
392 	iupdat(ip, &time, &time, 1);
393 
394 	wdir(ip);
395 	return(ip);
396 }
397 
398 /*
399  * Write a directory entry with
400  * parameters left as side effects
401  * to a call to namei.
402  */
403 wdir(ip)
404 struct inode *ip;
405 {
406 
407 	u.u_dent.d_ino = ip->i_number;
408 	bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ);
409 	u.u_count = sizeof(struct direct);
410 	u.u_segflg = 1;
411 	u.u_base = (caddr_t)&u.u_dent;
412 	writei(u.u_pdir);
413 	iput(u.u_pdir);
414 }
415