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