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