|
|
1.1 root 1: /* iget.c 4.4 81/03/08 */
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/trace.h"
14: #include "../h/proc.h"
15:
16: #define INOHSZ 63
17: /* INOHASH can't depend on fstype as long as unmount changes fstyp to err-fs */
18: #define INOHASH(dev, ino) (((dev)+(ino))%INOHSZ)
19: struct inode *inohash[INOHSZ];
20: struct inode *ifreel;
21:
22: /*
23: * Initialize hash links for inodes
24: * and build inode free list.
25: */
26: ihinit()
27: {
28: register int i;
29: register struct inode *ip = inode;
30:
31: ifreel = inode;
32: for (i = 0; i < ninode-1; i++, ip++)
33: ip->i_hlink = ip + 1;
34: ip->i_hlink = NULL;
35: for (i = 0; i < INOHSZ; i++)
36: inohash[i] = NULL;
37: }
38:
39: /*
40: * Find an inode if it is incore.
41: * This is the equivalent, for inodes,
42: * of ``incore'' in bio.c or ``pfind'' in subr.c.
43: */
44: struct inode *
45: ifind(hp, ino)
46: register struct inode *hp;
47: register ino_t ino;
48: {
49: register struct inode *ip;
50:
51: for (ip = inohash[INOHASH(hp->i_dev,ino)]; ip; ip = ip->i_hlink)
52: if (ino==ip->i_number && hp->i_dev==ip->i_dev && hp->i_fstyp==ip->i_fstyp)
53: return (ip);
54: return ((struct inode *)0);
55: }
56:
57: /*
58: * default entry for file system switch entry `t_get'
59: * put the inode, set errno, and return null.
60: */
61: struct inode *
62: nullget(fip, dev, ino, ip)
63: struct inode *fip;
64: dev_t dev;
65: ino_t ino;
66: struct inode *ip;
67: {
68: iput(ip);
69: u.u_error = ENXIO;
70: return(NULL);
71: }
72:
73:
74: /*
75: * Look up an inode by filsys, i-number.
76: * filsys is denoted by some inode in that filesystem.
77: * If it is in core (in the inode structure),
78: * honor the locking protocol.
79: * If it is not in core, read it in from the
80: * specified device.
81: * If the inode is mounted on, perform
82: * the indicated indirection.
83: * In all cases, a pointer to a locked
84: * inode structure is returned.
85: *
86: * panic: iget mroot -- if the mounted file
87: * system root is missing
88: * "cannot happen"
89: */
90: struct inode *
91: iget(fip, dev, ino)
92: register struct inode *fip;
93: dev_t dev;
94: register ino_t ino;
95: {
96: register struct inode *ip;
97: register int slot;
98:
99: loop:
100: slot = INOHASH(dev, ino);
101: for (ip = inohash[slot]; ip; ip = ip->i_hlink) {
102: if(ino == ip->i_number && dev == ip->i_dev
103: && fip->i_fstyp == ip->i_fstyp) {
104: mloop:
105: if((ip->i_flag&ILOCK) != 0) {
106: ip->i_flag |= IWANT;
107: ip->i_count++; /* don't move! */
108: sleep((caddr_t)ip, PINOD);
109: ip->i_count--;
110: goto loop;
111: }
112: if((ip->i_flag&IMOUNT) != 0) {
113: if (ip->i_mroot == NULL)
114: panic("iget mroot");
115: ip = ip->i_mroot;
116: goto mloop;
117: }
118: ip->i_count++;
119: ip->i_flag |= ILOCK;
120: return(ip);
121: }
122: }
123: if(ifreel == NULL) {
124: tablefull("inode");
125: u.u_error = ENFILE;
126: return(NULL);
127: }
128: ip = ifreel;
129: ifreel = ip->i_hlink;
130: ip->i_hlink = inohash[slot];
131: inohash[slot] = ip;
132: ip->i_dev = dev;
133: ip->i_fstyp = fip->i_fstyp;
134: ip->i_number = ino;
135: ip->i_flag = ILOCK;
136: ip->i_count++;
137: ip->i_sptr = NULL;
138: ip->i_mroot = NULL;
139: ip->i_mpoint = fip->i_mpoint; /* namei will fill in */
140: return((*fstypsw[fip->i_fstyp].t_get)(fip, dev, ino, ip));
141: }
142:
143: /*
144: * Decrement reference count of
145: * an inode structure.
146: * On the last reference,
147: * write the inode out and if necessary,
148: * truncate and deallocate the file.
149: */
150:
151: iput(ip)
152: register struct inode *ip;
153: {
154: register int i;
155: register struct inode *jp;
156:
157: if(ip->i_count == 1) {
158: ip->i_flag |= ILOCK;
159: if(ip->i_nlink <= 0)
160: (*fstypsw[ip->i_fstyp].t_free)(ip);
161: (*fstypsw[ip->i_fstyp].t_put)(ip);
162: i = INOHASH(ip->i_dev, ip->i_number);
163: if (inohash[i] == ip)
164: inohash[i] = ip->i_hlink;
165: else {
166: for (jp = inohash[i]; jp; jp = jp->i_hlink)
167: if (jp->i_hlink == ip) {
168: jp->i_hlink = ip->i_hlink;
169: goto done;
170: }
171: panic("iput");
172: }
173: done:
174: prele(ip);
175: ip->i_hlink = ifreel;
176: ifreel = ip;
177: ip->i_flag = 0;
178: ip->i_number = 0;
179: } else if(ip->i_count == 0) {
180: panic("i_count==0");
181: printf("i_count==0, ip %x dev %x ino %d fstyp %d\n", ip, ip->i_dev,
182: ip->i_number, ip->i_fstyp);
183: return; /* that leaves the turkey locked (for safety) */
184: } else
185: prele(ip);
186: ip->i_count--;
187: }
188:
189: /*
190: * Check accessed and update flags on
191: * an inode structure.
192: * If any is on, update the inode
193: * with the current time.
194: * If waitfor is given, then must insure
195: * i/o order so wait for write to complete.
196: */
197: iupdat(ip, ta, tm, waitfor)
198: register struct inode *ip;
199: time_t *ta, *tm;
200: int waitfor;
201: {
202:
203: if((ip->i_flag&(IUPD|IACC|ICHG)) != 0)
204: (*fstypsw[ip->i_fstyp].t_updat)(ip, ta, tm, waitfor);
205: }
206:
207: /*
208: * create a non-disk inode for a file system type;
209: * the inode returned is plocked and must be either
210: * iput or prele'sed.
211: */
212: struct inode *
213: ifake(fstyp)
214: int fstyp;
215: {
216: struct inode *ip;
217: static ino_t ino=0;
218: ino_t inostart;
219: struct inode pi; /* primer */
220:
221: pi.i_dev = 0;
222: pi.i_fstyp = fstyp;
223: for(inostart=ino;;) {
224: ip = iget(&pi, 0, ino);
225: if (ip == NULL)
226: return(NULL);
227: if (ip->i_count == 1)
228: break;
229: /*
230: * This inode is still in use - pick another
231: */
232: iput(ip);
233: /*
234: * Make sure we haven't gone through all the inodes
235: */
236: if (inostart==++ino) {
237: tablefull("fake inode");
238: u.u_error = ENFILE;
239: return(NULL);
240: }
241: }
242: ip->i_mode = IFREG | (0666 & ~u.u_cmask);
243: ip->i_uid = u.u_uid;
244: ip->i_gid = u.u_gid;
245: ip->i_un.i_rdev = (dev_t)0;
246: ino = inostart+1;
247: return(ip);
248: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.