Commit | Line | Data |
---|---|---|
848f4c12 TL |
1 | #include "../h/param.h" |
2 | #include "../h/systm.h" | |
3 | #include "../h/mount.h" | |
4 | #include "../h/filsys.h" | |
5 | #include "../h/fblk.h" | |
6 | #include "../h/conf.h" | |
7 | #include "../h/buf.h" | |
8 | #include "../h/inode.h" | |
9 | #include "../h/ino.h" | |
10 | #include "../h/dir.h" | |
11 | #include "../h/user.h" | |
12 | typedef struct fblk *FBLKP; | |
13 | ||
14 | /* | |
15 | * alloc will obtain the next available | |
16 | * free disk block from the free list of | |
17 | * the specified device. | |
18 | * The super block has up to NICFREE remembered | |
19 | * free blocks; the last of these is read to | |
20 | * obtain NICFREE more . . . | |
21 | * | |
22 | * no space on dev x/y -- when | |
23 | * the free list is exhausted. | |
24 | */ | |
25 | struct buf * | |
26 | alloc(dev) | |
27 | dev_t dev; | |
28 | { | |
29 | daddr_t bno; | |
30 | register struct filsys *fp; | |
31 | register struct buf *bp; | |
32 | ||
33 | fp = getfs(dev); | |
34 | while(fp->s_flock) | |
35 | sleep((caddr_t)&fp->s_flock, PINOD); | |
36 | do { | |
37 | if(fp->s_nfree <= 0) | |
38 | goto nospace; | |
39 | if (fp->s_nfree > NICFREE) { | |
40 | prdev("Bad free count", dev); | |
41 | goto nospace; | |
42 | } | |
43 | bno = fp->s_free[--fp->s_nfree]; | |
44 | if(bno == 0) | |
45 | goto nospace; | |
46 | } while (badblock(fp, bno, dev)); | |
47 | if(fp->s_nfree <= 0) { | |
48 | fp->s_flock++; | |
49 | bp = bread(dev, bno); | |
50 | if ((bp->b_flags&B_ERROR) == 0) { | |
51 | fp->s_nfree = ((FBLKP)(bp->b_un.b_addr))->df_nfree; | |
52 | bcopy((caddr_t)((FBLKP)(bp->b_un.b_addr))->df_free, | |
53 | (caddr_t)fp->s_free, sizeof(fp->s_free)); | |
54 | } | |
55 | brelse(bp); | |
56 | fp->s_flock = 0; | |
57 | wakeup((caddr_t)&fp->s_flock); | |
58 | if (fp->s_nfree <=0) | |
59 | goto nospace; | |
60 | } | |
61 | bp = getblk(dev, bno); | |
62 | clrbuf(bp); | |
63 | fp->s_fmod = 1; | |
64 | return(bp); | |
65 | ||
66 | nospace: | |
67 | fp->s_nfree = 0; | |
68 | prdev("no space", dev); | |
69 | u.u_error = ENOSPC; | |
70 | return(NULL); | |
71 | } | |
72 | ||
73 | /* | |
74 | * place the specified disk block | |
75 | * back on the free list of the | |
76 | * specified device. | |
77 | */ | |
78 | free(dev, bno) | |
79 | dev_t dev; | |
80 | daddr_t bno; | |
81 | { | |
82 | register struct filsys *fp; | |
83 | register struct buf *bp; | |
84 | ||
85 | fp = getfs(dev); | |
86 | fp->s_fmod = 1; | |
87 | while(fp->s_flock) | |
88 | sleep((caddr_t)&fp->s_flock, PINOD); | |
89 | if (badblock(fp, bno, dev)) | |
90 | return; | |
91 | if(fp->s_nfree <= 0) { | |
92 | fp->s_nfree = 1; | |
93 | fp->s_free[0] = 0; | |
94 | } | |
95 | if(fp->s_nfree >= NICFREE) { | |
96 | fp->s_flock++; | |
97 | bp = getblk(dev, bno); | |
98 | ((FBLKP)(bp->b_un.b_addr))->df_nfree = fp->s_nfree; | |
99 | bcopy((caddr_t)fp->s_free, | |
100 | (caddr_t)((FBLKP)(bp->b_un.b_addr))->df_free, | |
101 | sizeof(fp->s_free)); | |
102 | fp->s_nfree = 0; | |
103 | bwrite(bp); | |
104 | fp->s_flock = 0; | |
105 | wakeup((caddr_t)&fp->s_flock); | |
106 | } | |
107 | fp->s_free[fp->s_nfree++] = bno; | |
108 | fp->s_fmod = 1; | |
109 | } | |
110 | ||
111 | /* | |
112 | * Check that a block number is in the | |
113 | * range between the I list and the size | |
114 | * of the device. | |
115 | * This is used mainly to check that a | |
116 | * garbage file system has not been mounted. | |
117 | * | |
118 | * bad block on dev x/y -- not in range | |
119 | */ | |
120 | badblock(fp, bn, dev) | |
121 | register struct filsys *fp; | |
122 | daddr_t bn; | |
123 | dev_t dev; | |
124 | { | |
125 | ||
126 | if (bn < fp->s_isize || bn >= fp->s_fsize) { | |
127 | prdev("bad block", dev); | |
128 | return(1); | |
129 | } | |
130 | return(0); | |
131 | } | |
132 | ||
133 | /* | |
134 | * Allocate an unused I node | |
135 | * on the specified device. | |
136 | * Used with file creation. | |
137 | * The algorithm keeps up to | |
138 | * NICINOD spare I nodes in the | |
139 | * super block. When this runs out, | |
140 | * a linear search through the | |
141 | * I list is instituted to pick | |
142 | * up NICINOD more. | |
143 | */ | |
144 | struct inode * | |
145 | ialloc(dev) | |
146 | dev_t dev; | |
147 | { | |
148 | register struct filsys *fp; | |
149 | register struct buf *bp; | |
150 | register struct inode *ip; | |
151 | int i; | |
152 | struct dinode *dp; | |
153 | ino_t ino; | |
154 | daddr_t adr; | |
155 | ||
156 | fp = getfs(dev); | |
157 | while(fp->s_ilock) | |
158 | sleep((caddr_t)&fp->s_ilock, PINOD); | |
159 | loop: | |
160 | if(fp->s_ninode > 0) { | |
161 | ino = fp->s_inode[--fp->s_ninode]; | |
162 | ip = iget(dev, ino); | |
163 | if(ip == NULL) | |
164 | return(NULL); | |
165 | if(ip->i_mode == 0) { | |
166 | for (i=0; i<NADDR; i++) | |
167 | ip->i_un.i_addr[i] = 0; | |
168 | fp->s_fmod = 1; | |
169 | return(ip); | |
170 | } | |
171 | /* | |
172 | * Inode was allocated after all. | |
173 | * Look some more. | |
174 | */ | |
175 | iput(ip); | |
176 | goto loop; | |
177 | } | |
178 | fp->s_ilock++; | |
179 | ino = 1; | |
180 | for(adr = SUPERB+1; adr < fp->s_isize; adr++) { | |
181 | bp = bread(dev, adr); | |
182 | if (bp->b_flags & B_ERROR) { | |
183 | brelse(bp); | |
184 | ino += INOPB; | |
185 | continue; | |
186 | } | |
187 | dp = bp->b_un.b_dino; | |
188 | for(i=0; i<INOPB; i++) { | |
189 | if(dp->di_mode != 0) | |
190 | goto cont; | |
191 | for(ip = &inode[0]; ip < &inode[NINODE]; ip++) | |
192 | if(dev==ip->i_dev && ino==ip->i_number) | |
193 | goto cont; | |
194 | fp->s_inode[fp->s_ninode++] = ino; | |
195 | if(fp->s_ninode >= NICINOD) | |
196 | break; | |
197 | cont: | |
198 | ino++; | |
199 | dp++; | |
200 | } | |
201 | brelse(bp); | |
202 | if(fp->s_ninode >= NICINOD) | |
203 | break; | |
204 | } | |
205 | fp->s_ilock = 0; | |
206 | wakeup((caddr_t)&fp->s_ilock); | |
207 | if(fp->s_ninode > 0) | |
208 | goto loop; | |
209 | prdev("Out of inodes", dev); | |
210 | u.u_error = ENOSPC; | |
211 | return(NULL); | |
212 | } | |
213 | ||
214 | /* | |
215 | * Free the specified I node | |
216 | * on the specified device. | |
217 | * The algorithm stores up | |
218 | * to NICINOD I nodes in the super | |
219 | * block and throws away any more. | |
220 | */ | |
221 | ifree(dev, ino) | |
222 | dev_t dev; | |
223 | ino_t ino; | |
224 | { | |
225 | register struct filsys *fp; | |
226 | ||
227 | fp = getfs(dev); | |
228 | if(fp->s_ilock) | |
229 | return; | |
230 | if(fp->s_ninode >= NICINOD) | |
231 | return; | |
232 | fp->s_inode[fp->s_ninode++] = ino; | |
233 | fp->s_fmod = 1; | |
234 | } | |
235 | ||
236 | /* | |
237 | * getfs maps a device number into | |
238 | * a pointer to the incore super | |
239 | * block. | |
240 | * The algorithm is a linear | |
241 | * search through the mount table. | |
242 | * A consistency check of the | |
243 | * in core free-block and i-node | |
244 | * counts. | |
245 | * | |
246 | * bad count on dev x/y -- the count | |
247 | * check failed. At this point, all | |
248 | * the counts are zeroed which will | |
249 | * almost certainly lead to "no space" | |
250 | * diagnostic | |
251 | * panic: no fs -- the device is not mounted. | |
252 | * this "cannot happen" | |
253 | */ | |
254 | struct filsys * | |
255 | getfs(dev) | |
256 | dev_t dev; | |
257 | { | |
258 | register struct mount *mp; | |
259 | register struct filsys *fp; | |
260 | ||
261 | for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) | |
262 | if(mp->m_bufp != NULL && mp->m_dev == dev) { | |
263 | fp = mp->m_bufp->b_un.b_filsys; | |
264 | if(fp->s_nfree > NICFREE || fp->s_ninode > NICINOD) { | |
265 | prdev("bad count", dev); | |
266 | fp->s_nfree = 0; | |
267 | fp->s_ninode = 0; | |
268 | } | |
269 | return(fp); | |
270 | } | |
271 | panic("no fs"); | |
272 | return(NULL); | |
273 | } | |
274 | ||
275 | /* | |
276 | * update is the internal name of | |
277 | * 'sync'. It goes through the disk | |
278 | * queues to initiate sandbagged IO; | |
279 | * goes through the I nodes to write | |
280 | * modified nodes; and it goes through | |
281 | * the mount table to initiate modified | |
282 | * super blocks. | |
283 | */ | |
284 | update() | |
285 | { | |
286 | register struct inode *ip; | |
287 | register struct mount *mp; | |
288 | register struct buf *bp; | |
289 | struct filsys *fp; | |
290 | ||
291 | if(updlock) | |
292 | return; | |
293 | updlock++; | |
294 | for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) | |
295 | if(mp->m_bufp != NULL) { | |
296 | fp = mp->m_bufp->b_un.b_filsys; | |
297 | if(fp->s_fmod==0 || fp->s_ilock!=0 || | |
298 | fp->s_flock!=0 || fp->s_ronly!=0) | |
299 | continue; | |
300 | bp = getblk(mp->m_dev, SUPERB); | |
301 | if (bp->b_flags & B_ERROR) | |
302 | continue; | |
303 | fp->s_fmod = 0; | |
304 | fp->s_time = time; | |
305 | bcopy((caddr_t)fp, bp->b_un.b_addr, BSIZE); | |
306 | bwrite(bp); | |
307 | } | |
308 | for(ip = &inode[0]; ip < &inode[NINODE]; ip++) | |
309 | if((ip->i_flag&ILOCK)==0 && ip->i_count) { | |
310 | ip->i_flag |= ILOCK; | |
311 | ip->i_count++; | |
312 | iupdat(ip, &time, &time); | |
313 | iput(ip); | |
314 | } | |
315 | updlock = 0; | |
316 | bflush(NODEV); | |
317 | } |