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