xref: /original-bsd/sys/ufs/ufs/ufs_inode.c (revision d25e1985)
1 /*	ufs_inode.c	3.4	07/08/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);
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  */
212 iupdat(ip, ta, tm)
213 register struct inode *ip;
214 time_t *ta, *tm;
215 {
216 	register struct buf *bp;
217 	struct dinode *dp;
218 	register char *p1, *p2;
219 	register int i;
220 
221 	if((ip->i_flag&(IUPD|IACC|ICHG)) != 0) {
222 		if(getfs(ip->i_dev)->s_ronly)
223 			return;
224 		bp = bread(ip->i_dev, itod(ip->i_number));
225 		if (bp->b_flags & B_ERROR) {
226 			brelse(bp);
227 			return;
228 		}
229 		dp = bp->b_un.b_dino;
230 		dp += itoo(ip->i_number);
231 		dp->di_mode = ip->i_mode;
232 		dp->di_nlink = ip->i_nlink;
233 		dp->di_uid = ip->i_uid;
234 		dp->di_gid = ip->i_gid;
235 		dp->di_size = ip->i_size;
236 		p1 = (char *)dp->di_addr;
237 		p2 = (char *)ip->i_un.i_addr;
238 		for(i=0; i<NADDR; i++) {
239 			*p1++ = *p2++;
240 			*p1++ = *p2++;
241 			*p1++ = *p2++;
242 			if(*p2++ != 0 && (ip->i_mode&IFMT)!=IFMPC
243 			   && (ip->i_mode&IFMT)!=IFMPB)
244 				printf("iaddress > 2^24\n");
245 		}
246 		if(ip->i_flag&IACC)
247 			dp->di_atime = *ta;
248 		if(ip->i_flag&IUPD)
249 			dp->di_mtime = *tm;
250 		if(ip->i_flag&ICHG)
251 			dp->di_ctime = time;
252 		ip->i_flag &= ~(IUPD|IACC|ICHG);
253 		bdwrite(bp);
254 	}
255 }
256 
257 /*
258  * Free all the disk blocks associated
259  * with the specified inode structure.
260  * The blocks of the file are removed
261  * in reverse order. This FILO
262  * algorithm will tend to maintain
263  * a contiguous free list much longer
264  * than FIFO.
265  */
266 itrunc(ip)
267 register struct inode *ip;
268 {
269 	register i;
270 	dev_t dev;
271 	daddr_t bn;
272 
273 	if (ip->i_vfdcnt)
274 		panic("itrunc");
275 	i = ip->i_mode & IFMT;
276 	if (i!=IFREG && i!=IFDIR)
277 		return;
278 	dev = ip->i_dev;
279 	for(i=NADDR-1; i>=0; i--) {
280 		bn = ip->i_un.i_addr[i];
281 		if(bn == (daddr_t)0)
282 			continue;
283 		ip->i_un.i_addr[i] = (daddr_t)0;
284 		switch(i) {
285 
286 		default:
287 			free(dev, bn);
288 			break;
289 
290 		case NADDR-3:
291 			tloop(dev, bn, 0, 0);
292 			break;
293 
294 		case NADDR-2:
295 			tloop(dev, bn, 1, 0);
296 			break;
297 
298 		case NADDR-1:
299 			tloop(dev, bn, 1, 1);
300 		}
301 	}
302 	ip->i_size = 0;
303 	ip->i_flag |= ICHG|IUPD;
304 }
305 
306 tloop(dev, bn, f1, f2)
307 dev_t dev;
308 daddr_t bn;
309 {
310 	register i;
311 	register struct buf *bp;
312 	register daddr_t *bap;
313 	daddr_t nb;
314 
315 	bp = NULL;
316 	for(i=NINDIR-1; i>=0; i--) {
317 		if(bp == NULL) {
318 			bp = bread(dev, bn);
319 			if (bp->b_flags & B_ERROR) {
320 				brelse(bp);
321 				return;
322 			}
323 			bap = bp->b_un.b_daddr;
324 		}
325 		nb = bap[i];
326 		if(nb == (daddr_t)0)
327 			continue;
328 		if(f1) {
329 			brelse(bp);
330 			bp = NULL;
331 			tloop(dev, nb, f2, 0);
332 		} else
333 			free(dev, nb);
334 	}
335 	if(bp != NULL)
336 		brelse(bp);
337 	free(dev, bn);
338 }
339 
340 /*
341  * Make a new file.
342  */
343 struct inode *
344 maknode(mode)
345 {
346 	register struct inode *ip;
347 
348 	ip = ialloc(u.u_pdir->i_dev);
349 	if(ip == NULL) {
350 		iput(u.u_pdir);
351 		return(NULL);
352 	}
353 	ip->i_flag |= IACC|IUPD|ICHG;
354 	if((mode&IFMT) == 0)
355 		mode |= IFREG;
356 	ip->i_mode = mode & ~u.u_cmask;
357 	ip->i_nlink = 1;
358 	ip->i_uid = u.u_uid;
359 	ip->i_gid = u.u_gid;
360 	wdir(ip);
361 	return(ip);
362 }
363 
364 /*
365  * Write a directory entry with
366  * parameters left as side effects
367  * to a call to namei.
368  */
369 wdir(ip)
370 struct inode *ip;
371 {
372 
373 	u.u_dent.d_ino = ip->i_number;
374 	bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ);
375 	u.u_count = sizeof(struct direct);
376 	u.u_segflg = 1;
377 	u.u_base = (caddr_t)&u.u_dent;
378 	writei(u.u_pdir);
379 	iput(u.u_pdir);
380 }
381