|
|
1.1 root 1: #include "sys/param.h"
2: #include "sys/user.h"
3: #include "sys/inode.h"
4: #include "sys/conf.h"
5:
6: #define INOHSZ 63
7: /* INOHASH can't depend on fstype as long as unmount changes fstyp to err-fs */
8: #define INOHASH(dev, ino) (((dev)+(ino))%INOHSZ)
9: struct inode *inohash[INOHSZ];
10: struct inode *ifreel;
11:
12: /*
13: * Initialize hash links for inodes
14: * and build inode free list.
15: */
16: ihinit()
17: {
18: register int i;
19: register struct inode *ip = inode;
20:
21: ifreel = inode;
22: for (i = 0; i < inodecnt-1; i++, ip++)
23: ip->i_hlink = ip + 1;
24: ip->i_hlink = NULL;
25: for (i = 0; i < INOHSZ; i++)
26: inohash[i] = NULL;
27: }
28:
29: /*
30: * Find an inode if it is incore.
31: */
32: struct inode *
33: ifind(hp, ino)
34: register struct inode *hp;
35: register ino_t ino;
36: {
37: register struct inode *ip;
38:
39: for (ip = inohash[INOHASH(hp->i_dev,ino)]; ip; ip = ip->i_hlink)
40: if (ino==ip->i_number && hp->i_dev==ip->i_dev && hp->i_fstyp==ip->i_fstyp)
41: return (ip);
42: return ((struct inode *)0);
43: }
44:
45: /*
46: * see if there are any inodes save the given one
47: * in the same filesystem
48: * used by unmount routines to decide whether fs is busy
49: * try to unmount anything mounted atop this fs
50: * -- botch: deeply nested filesystems may run the system
51: * out of stack and cause a crash
52: */
53:
54: int
55: ifsbusy(rip)
56: register struct inode *rip;
57: {
58: register struct inode *ip;
59:
60: for (ip = inode; ip < inodeNINODE; ip++) {
61: if (ip->i_count == 0)
62: continue;
63: if (ip->i_mpoint != rip->i_mpoint)
64: continue;
65: if (ip->i_mroot) { /* something mounted here? */
66: ip->i_count++;
67: (*fstypsw[ip->i_mroot->i_fstyp]->t_mount)((struct inode *)NULL,
68: ip, 0, 0, ip->i_mroot->i_fstyp);
69: if (ip->i_count == 1) { /* just our reference left? */
70: idec(ip);
71: continue;
72: }
73: idec(ip);
74: }
75: if (ip != rip)
76: return (1);
77: }
78: return (0);
79: }
80:
81: /*
82: * mark inaccessible all i-nodes in this filesystem
83: * used for forced unmounting
84: * any further IO through those inodes will produce an error
85: * -- it's annoying that ERRFS must be manifest
86: */
87:
88: #define ERRFS 5
89: ifsinacc(rip)
90: register struct inode *rip;
91: {
92: register struct inode *ip;
93:
94: rip = rip->i_mpoint;
95: for (ip = inode; ip < inodeNINODE; ip++) {
96: if (ip->i_count == 0)
97: continue;
98: if (ip->i_mpoint != rip)
99: continue;
100: ip->i_fstyp = ERRFS; /* yes, always */
101: ip->i_mpoint = rootdir; /* hmm */
102: if (ip->i_mroot)
103: (*fstypsw[ip->i_mroot->i_fstyp]->t_mount)((struct inode *)NULL,
104: ip, 0, 0, ip->i_mroot->i_fstyp);
105: }
106: }
107:
108: #ifndef plock /* done inline */
109: /*
110: * Lock an inode
111: * If its already locked,
112: * set the WANT bit and sleep.
113: */
114: plock(ip)
115: register struct inode *ip;
116: {
117:
118: while(ip->i_flag&ILOCK) {
119: ip->i_flag |= IWANT;
120: sleep((caddr_t)ip, PINOD);
121: }
122: ip->i_flag |= ILOCK;
123: }
124:
125: /*
126: * Unlock an inode.
127: * If WANT bit is on,
128: * wakeup.
129: */
130: prele(ip)
131: register struct inode *ip;
132: {
133: ip->i_flag &= ~ILOCK;
134: if(ip->i_flag&IWANT) {
135: ip->i_flag &= ~IWANT;
136: wakeup((caddr_t)ip);
137: }
138: }
139: #endif
140:
141:
142: /*
143: * Look up an inode by filsys, i-number.
144: * filsys is denoted by some inode in that filesystem.
145: * If the inode is mounted on, perform
146: * the indicated indirection.
147: * If it is in core (in the inode structure),
148: * honor the locking protocol.
149: * If it is not in core, fill in the fields that
150: * signify the inode`s `name' (number, dev, filsys, fstyp)
151: * and leave the rest blank, to be filled in by the caller.
152: * A `blank' inode has i_count == 1.
153: * In all cases, a pointer to a locked
154: * inode structure is returned.
155: */
156: struct inode *
157: iget(fip, dev, ino)
158: register struct inode *fip;
159: dev_t dev;
160: register ino_t ino;
161: {
162: register struct inode *ip;
163: register int slot;
164:
165: loop:
166: slot = INOHASH(dev, ino);
167: for (ip = inohash[slot]; ip; ip = ip->i_hlink) {
168: if(ino == ip->i_number && dev == ip->i_dev
169: && fip->i_fstyp == ip->i_fstyp) {
170: mloop:
171: if((ip->i_flag&ILOCK) != 0) {
172: ip->i_flag |= IWANT;
173: sleep((caddr_t)ip, PINOD);
174: goto loop;
175: }
176: if(ip->i_mroot != NULL) {
177: ip = ip->i_mroot;
178: goto mloop;
179: }
180: ip->i_count++;
181: ip->i_flag |= ILOCK;
182: return(ip);
183: }
184: }
185: if(ifreel == NULL) {
186: tablefull("inode");
187: u.u_error = ENFILE;
188: return(NULL);
189: }
190: ip = ifreel;
191: ifreel = ip->i_hlink;
192: ip->i_hlink = inohash[slot];
193: inohash[slot] = ip;
194: ip->i_dev = dev;
195: ip->i_fstyp = fip->i_fstyp;
196: ip->i_number = ino;
197: ip->i_flag = ILOCK;
198: ip->i_count = 1;
199: ip->i_sptr = NULL;
200: ip->i_mroot = NULL;
201: ip->i_mpoint = fip->i_mpoint;
202: return (ip);
203: }
204:
205: /*
206: * Decrement reference count of
207: * an inode structure.
208: * On the last reference,
209: * call closei to close the file.
210: * Don't unlock unless we were the only reference.
211: */
212: idec(ip)
213: register struct inode *ip;
214: {
215: register int i;
216: register struct inode *jp;
217:
218: if (ip->i_count == 0)
219: panic("i_count==0");
220: if (ip->i_count == 1) {
221: ip->i_flag |= ILOCK;
222: closei(ip);
223: (*fstypsw[ip->i_fstyp]->t_put)(ip);
224: i = INOHASH(ip->i_dev, ip->i_number);
225: if (inohash[i] == ip)
226: inohash[i] = ip->i_hlink;
227: else {
228: for (jp = inohash[i]; jp; jp = jp->i_hlink)
229: if (jp->i_hlink == ip) {
230: jp->i_hlink = ip->i_hlink;
231: goto done;
232: }
233: panic("idec");
234: }
235: done:
236: prele(ip);
237: ip->i_flag = 0;
238: ip->i_number = 0;
239: ip->i_hlink = ifreel;
240: ifreel = ip;
241: }
242: ip->i_count--;
243: }
244:
245: /*
246: * decrement the count for a locked inode.
247: * unlock.
248: * perhaps this should be a macro later
249: */
250:
251: iput(ip)
252: register struct inode *ip;
253: {
254: #if NOTDEF
255: if ((ip->i_flag & ILOCK) == 0)
256: panic("iput");
257: #endif
258: if (ip->i_count == 0)
259: panic("i_count==0");
260: if (ip->i_count == 1)
261: idec(ip); /* will take care of lock too */
262: else {
263: ip->i_count--;
264: prele(ip);
265: }
266: }
267:
268: /*
269: * Check accessed and update flags on
270: * an inode structure.
271: * If any is on, update the inode
272: * with the current time.
273: * If waitfor is given, then must insure
274: * i/o order so wait for write to complete.
275: */
276: iupdat(ip, ta, tm, waitfor)
277: register struct inode *ip;
278: time_t *ta, *tm;
279: int waitfor;
280: {
281:
282: if((ip->i_flag&(IUPD|IACC|ICHG)) != 0)
283: (*fstypsw[ip->i_fstyp]->t_updat)(ip, ta, tm, waitfor);
284: }
285:
286: /*
287: * allocate an in-core-only inode with no filesystem counterpart
288: * used for pipes and similar things
289: * a locked inode is returned, filled in and useable,
290: * but not a member of any filesystem
291: */
292: struct inode *
293: iuniq(fstyp)
294: int fstyp;
295: {
296: struct inode *ip;
297: static ino_t ino=0;
298: ino_t inostart;
299: struct inode pi; /* primer */
300:
301: pi.i_dev = NODEV;
302: pi.i_fstyp = fstyp;
303: pi.i_mpoint = NULL;
304: for (inostart = ino++; ino != inostart; ino++) {
305: if (ifind(&pi, ino)) /* already in use */
306: continue;
307: if ((ip = iget(&pi, NODEV, ino)) == NULL)
308: return (NULL); /* no inodes, or something */
309: if (ip->i_count != 1) { /* already in use -- safety */
310: iput(ip);
311: continue;
312: }
313: ip->i_mode = IFREG | (0666 & ~u.u_cmask);
314: ip->i_uid = u.u_uid;
315: ip->i_gid = u.u_gid;
316: ip->i_nlink = 0;
317: return(ip);
318: }
319: tablefull("fake inode");
320: u.u_error = ENFILE;
321: return(NULL);
322: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.