Commit | Line | Data |
---|---|---|
5e1d8839 | 1 | /* alloc.c 4.1 82/03/25 */ |
e3fe2d69 | 2 | |
5e1d8839 | 3 | /* merged into kernel: @(#)ffs_alloc.c 2.2 %G% */ |
e3fe2d69 | 4 | |
5e1d8839 | 5 | /* last monet version: alloc.c 4.8 81/03/08 */ |
e3fe2d69 KM |
6 | |
7 | #include "../h/param.h" | |
8 | #include "../h/systm.h" | |
9 | #include "../h/mount.h" | |
10 | #include "../h/fs.h" | |
11 | #include "../h/conf.h" | |
12 | #include "../h/buf.h" | |
13 | #include "../h/inode.h" | |
ce29a78b | 14 | #include "../h/ndir.h" |
e3fe2d69 KM |
15 | #include "../h/user.h" |
16 | ||
daaf7bee KM |
17 | extern u_long hashalloc(); |
18 | extern ino_t ialloccg(); | |
743f1ef7 KM |
19 | extern daddr_t alloccg(); |
20 | extern daddr_t alloccgblk(); | |
21 | extern daddr_t fragextend(); | |
22 | extern daddr_t blkpref(); | |
23 | extern daddr_t mapsearch(); | |
1d7a08c5 | 24 | extern int inside[], around[]; |
b6407c9d | 25 | extern unsigned char *fragtbl[]; |
e3fe2d69 | 26 | |
502770a3 KM |
27 | /* |
28 | * Allocate a block in the file system. | |
29 | * | |
30 | * The size of the requested block is given, which must be some | |
31 | * multiple of fs_fsize and <= fs_bsize. | |
32 | * A preference may be optionally specified. If a preference is given | |
33 | * the following hierarchy is used to allocate a block: | |
34 | * 1) allocate the requested block. | |
35 | * 2) allocate a rotationally optimal block in the same cylinder. | |
36 | * 3) allocate a block in the same cylinder group. | |
37 | * 4) quadradically rehash into other cylinder groups, until an | |
38 | * available block is located. | |
39 | * If no block preference is given the following heirarchy is used | |
40 | * to allocate a block: | |
41 | * 1) allocate a block in the cylinder group that contains the | |
42 | * inode for the file. | |
43 | * 2) quadradically rehash into other cylinder groups, until an | |
44 | * available block is located. | |
45 | */ | |
e3fe2d69 | 46 | struct buf * |
f7287e4b | 47 | alloc(ip, bpref, size) |
f3c028b7 | 48 | register struct inode *ip; |
e3fe2d69 KM |
49 | daddr_t bpref; |
50 | int size; | |
51 | { | |
52 | daddr_t bno; | |
53 | register struct fs *fs; | |
f3c028b7 | 54 | register struct buf *bp; |
e3fe2d69 KM |
55 | int cg; |
56 | ||
f7287e4b | 57 | fs = ip->i_fs; |
d995d89d | 58 | if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) |
b6407c9d KM |
59 | panic("alloc: bad size"); |
60 | if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0) | |
0947395d KM |
61 | goto nospace; |
62 | if (u.u_uid != 0 && | |
b6407c9d KM |
63 | fs->fs_cstotal.cs_nbfree * fs->fs_frag + fs->fs_cstotal.cs_nffree < |
64 | fs->fs_dsize * fs->fs_minfree / 100) | |
e3fe2d69 | 65 | goto nospace; |
260e5e3c KM |
66 | if (bpref >= fs->fs_size) |
67 | bpref = 0; | |
e3fe2d69 | 68 | if (bpref == 0) |
6994bf5d | 69 | cg = itog(fs, ip->i_number); |
e3fe2d69 | 70 | else |
6994bf5d | 71 | cg = dtog(fs, bpref); |
f7287e4b | 72 | bno = (daddr_t)hashalloc(ip, cg, (long)bpref, size, alloccg); |
e3fe2d69 KM |
73 | if (bno == 0) |
74 | goto nospace; | |
f7287e4b | 75 | bp = getblk(ip->i_dev, fsbtodb(fs, bno), size); |
e3fe2d69 KM |
76 | clrbuf(bp); |
77 | return (bp); | |
78 | nospace: | |
79 | fserr(fs, "file system full"); | |
80 | uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); | |
81 | u.u_error = ENOSPC; | |
82 | return (NULL); | |
83 | } | |
84 | ||
502770a3 KM |
85 | /* |
86 | * Reallocate a fragment to a bigger size | |
87 | * | |
88 | * The number and size of the old block is given, and a preference | |
89 | * and new size is also specified. The allocator attempts to extend | |
90 | * the original block. Failing that, the regular block allocator is | |
91 | * invoked to get an appropriate block. | |
92 | */ | |
07670f7d | 93 | struct buf * |
f7287e4b KM |
94 | realloccg(ip, bprev, bpref, osize, nsize) |
95 | register struct inode *ip; | |
743f1ef7 | 96 | daddr_t bprev, bpref; |
07670f7d KM |
97 | int osize, nsize; |
98 | { | |
99 | daddr_t bno; | |
100 | register struct fs *fs; | |
f3c028b7 KM |
101 | register struct buf *bp, *obp; |
102 | caddr_t cp; | |
07670f7d KM |
103 | int cg; |
104 | ||
f7287e4b | 105 | fs = ip->i_fs; |
d995d89d KM |
106 | if ((unsigned)osize > fs->fs_bsize || fragoff(fs, osize) != 0 || |
107 | (unsigned)nsize > fs->fs_bsize || fragoff(fs, nsize) != 0) | |
b6407c9d | 108 | panic("realloccg: bad size"); |
0947395d | 109 | if (u.u_uid != 0 && |
b6407c9d KM |
110 | fs->fs_cstotal.cs_nbfree * fs->fs_frag + fs->fs_cstotal.cs_nffree < |
111 | fs->fs_dsize * fs->fs_minfree / 100) | |
0947395d | 112 | goto nospace; |
ae851115 | 113 | if (bprev == 0) |
502770a3 | 114 | panic("realloccg: bad bprev"); |
ae851115 | 115 | cg = dtog(fs, bprev); |
f7287e4b | 116 | bno = fragextend(ip, cg, (long)bprev, osize, nsize); |
f3c028b7 | 117 | if (bno != 0) { |
f7287e4b | 118 | bp = bread(ip->i_dev, fsbtodb(fs, bno), osize); |
d995d89d KM |
119 | if (bp->b_flags & B_ERROR) { |
120 | brelse(bp); | |
ae851115 | 121 | return (NULL); |
d995d89d | 122 | } |
f3c028b7 KM |
123 | bp->b_bcount = nsize; |
124 | blkclr(bp->b_un.b_addr + osize, nsize - osize); | |
125 | return (bp); | |
126 | } | |
260e5e3c KM |
127 | if (bpref >= fs->fs_size) |
128 | bpref = 0; | |
f7287e4b | 129 | bno = (daddr_t)hashalloc(ip, cg, (long)bpref, nsize, alloccg); |
f3c028b7 KM |
130 | if (bno != 0) { |
131 | /* | |
132 | * make a new copy | |
133 | */ | |
f7287e4b | 134 | obp = bread(ip->i_dev, fsbtodb(fs, bprev), osize); |
d995d89d KM |
135 | if (obp->b_flags & B_ERROR) { |
136 | brelse(obp); | |
ae851115 | 137 | return (NULL); |
d995d89d | 138 | } |
f7287e4b | 139 | bp = getblk(ip->i_dev, fsbtodb(fs, bno), nsize); |
f3c028b7 KM |
140 | cp = bp->b_un.b_addr; |
141 | bp->b_un.b_addr = obp->b_un.b_addr; | |
142 | obp->b_un.b_addr = cp; | |
143 | obp->b_flags |= B_INVAL; | |
144 | brelse(obp); | |
f7287e4b | 145 | fre(ip, bprev, (off_t)osize); |
f3c028b7 | 146 | blkclr(bp->b_un.b_addr + osize, nsize - osize); |
ae851115 | 147 | return (bp); |
f3c028b7 | 148 | } |
0947395d | 149 | nospace: |
f3c028b7 KM |
150 | /* |
151 | * no space available | |
152 | */ | |
07670f7d KM |
153 | fserr(fs, "file system full"); |
154 | uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); | |
155 | u.u_error = ENOSPC; | |
156 | return (NULL); | |
157 | } | |
158 | ||
502770a3 KM |
159 | /* |
160 | * Allocate an inode in the file system. | |
161 | * | |
162 | * A preference may be optionally specified. If a preference is given | |
163 | * the following hierarchy is used to allocate an inode: | |
164 | * 1) allocate the requested inode. | |
165 | * 2) allocate an inode in the same cylinder group. | |
166 | * 3) quadradically rehash into other cylinder groups, until an | |
167 | * available inode is located. | |
168 | * If no inode preference is given the following heirarchy is used | |
169 | * to allocate an inode: | |
170 | * 1) allocate an inode in cylinder group 0. | |
171 | * 2) quadradically rehash into other cylinder groups, until an | |
172 | * available inode is located. | |
173 | */ | |
e3fe2d69 | 174 | struct inode * |
f7287e4b KM |
175 | ialloc(pip, ipref, mode) |
176 | register struct inode *pip; | |
e3fe2d69 KM |
177 | ino_t ipref; |
178 | int mode; | |
179 | { | |
daaf7bee | 180 | ino_t ino; |
e3fe2d69 KM |
181 | register struct fs *fs; |
182 | register struct inode *ip; | |
183 | int cg; | |
184 | ||
f7287e4b | 185 | fs = pip->i_fs; |
0947395d | 186 | if (fs->fs_cstotal.cs_nifree == 0) |
e3fe2d69 | 187 | goto noinodes; |
260e5e3c KM |
188 | if (ipref >= fs->fs_ncg * fs->fs_ipg) |
189 | ipref = 0; | |
6994bf5d | 190 | cg = itog(fs, ipref); |
f7287e4b | 191 | ino = (ino_t)hashalloc(pip, cg, (long)ipref, mode, ialloccg); |
e3fe2d69 KM |
192 | if (ino == 0) |
193 | goto noinodes; | |
f7287e4b | 194 | ip = iget(pip->i_dev, pip->i_fs, ino); |
e3fe2d69 | 195 | if (ip == NULL) { |
f7287e4b | 196 | ifree(ip, ino, 0); |
e3fe2d69 KM |
197 | return (NULL); |
198 | } | |
199 | if (ip->i_mode) | |
200 | panic("ialloc: dup alloc"); | |
201 | return (ip); | |
202 | noinodes: | |
203 | fserr(fs, "out of inodes"); | |
ae851115 | 204 | uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt); |
e3fe2d69 KM |
205 | u.u_error = ENOSPC; |
206 | return (NULL); | |
207 | } | |
208 | ||
743f1ef7 | 209 | /* |
502770a3 KM |
210 | * Find a cylinder to place a directory. |
211 | * | |
212 | * The policy implemented by this algorithm is to select from | |
213 | * among those cylinder groups with above the average number of | |
214 | * free inodes, the one with the smallest number of directories. | |
743f1ef7 | 215 | */ |
f7287e4b | 216 | dirpref(fs) |
e3fe2d69 | 217 | register struct fs *fs; |
f7287e4b | 218 | { |
743f1ef7 | 219 | int cg, minndir, mincg, avgifree; |
e3fe2d69 | 220 | |
0947395d | 221 | avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg; |
743f1ef7 | 222 | minndir = fs->fs_ipg; |
e3fe2d69 | 223 | mincg = 0; |
743f1ef7 | 224 | for (cg = 0; cg < fs->fs_ncg; cg++) |
b6407c9d KM |
225 | if (fs->fs_cs(fs, cg).cs_ndir < minndir && |
226 | fs->fs_cs(fs, cg).cs_nifree >= avgifree) { | |
e3fe2d69 | 227 | mincg = cg; |
b6407c9d | 228 | minndir = fs->fs_cs(fs, cg).cs_ndir; |
e3fe2d69 KM |
229 | } |
230 | return (fs->fs_ipg * mincg); | |
231 | } | |
232 | ||
743f1ef7 | 233 | /* |
502770a3 KM |
234 | * Select a cylinder to place a large block of data. |
235 | * | |
236 | * The policy implemented by this algorithm is to maintain a | |
237 | * rotor that sweeps the cylinder groups. When a block is | |
238 | * needed, the rotor is advanced until a cylinder group with | |
239 | * greater than the average number of free blocks is found. | |
743f1ef7 | 240 | */ |
daaf7bee | 241 | daddr_t |
f7287e4b | 242 | blkpref(fs) |
743f1ef7 | 243 | register struct fs *fs; |
f7287e4b | 244 | { |
743f1ef7 KM |
245 | int cg, avgbfree; |
246 | ||
0947395d | 247 | avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; |
743f1ef7 | 248 | for (cg = fs->fs_cgrotor + 1; cg < fs->fs_ncg; cg++) |
b6407c9d | 249 | if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { |
743f1ef7 | 250 | fs->fs_cgrotor = cg; |
b6407c9d | 251 | return (fs->fs_fpg * cg + fs->fs_frag); |
743f1ef7 KM |
252 | } |
253 | for (cg = 0; cg <= fs->fs_cgrotor; cg++) | |
b6407c9d | 254 | if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { |
743f1ef7 | 255 | fs->fs_cgrotor = cg; |
b6407c9d | 256 | return (fs->fs_fpg * cg + fs->fs_frag); |
743f1ef7 | 257 | } |
ae851115 | 258 | return (NULL); |
743f1ef7 KM |
259 | } |
260 | ||
502770a3 KM |
261 | /* |
262 | * Implement the cylinder overflow algorithm. | |
263 | * | |
264 | * The policy implemented by this algorithm is: | |
265 | * 1) allocate the block in its requested cylinder group. | |
266 | * 2) quadradically rehash on the cylinder group number. | |
267 | * 3) brute force search for a free block. | |
268 | */ | |
daaf7bee KM |
269 | /*VARARGS5*/ |
270 | u_long | |
f7287e4b KM |
271 | hashalloc(ip, cg, pref, size, allocator) |
272 | struct inode *ip; | |
e3fe2d69 KM |
273 | int cg; |
274 | long pref; | |
275 | int size; /* size for data blocks, mode for inodes */ | |
daaf7bee | 276 | u_long (*allocator)(); |
e3fe2d69 | 277 | { |
f7287e4b | 278 | register struct fs *fs; |
e3fe2d69 KM |
279 | long result; |
280 | int i, icg = cg; | |
281 | ||
f7287e4b | 282 | fs = ip->i_fs; |
e3fe2d69 KM |
283 | /* |
284 | * 1: preferred cylinder group | |
285 | */ | |
f7287e4b | 286 | result = (*allocator)(ip, cg, pref, size); |
e3fe2d69 KM |
287 | if (result) |
288 | return (result); | |
289 | /* | |
290 | * 2: quadratic rehash | |
291 | */ | |
292 | for (i = 1; i < fs->fs_ncg; i *= 2) { | |
293 | cg += i; | |
294 | if (cg >= fs->fs_ncg) | |
295 | cg -= fs->fs_ncg; | |
f7287e4b | 296 | result = (*allocator)(ip, cg, 0, size); |
e3fe2d69 KM |
297 | if (result) |
298 | return (result); | |
299 | } | |
300 | /* | |
301 | * 3: brute force search | |
302 | */ | |
303 | cg = icg; | |
304 | for (i = 0; i < fs->fs_ncg; i++) { | |
f7287e4b | 305 | result = (*allocator)(ip, cg, 0, size); |
e3fe2d69 KM |
306 | if (result) |
307 | return (result); | |
308 | cg++; | |
309 | if (cg == fs->fs_ncg) | |
310 | cg = 0; | |
311 | } | |
ae851115 | 312 | return (NULL); |
e3fe2d69 KM |
313 | } |
314 | ||
502770a3 KM |
315 | /* |
316 | * Determine whether a fragment can be extended. | |
317 | * | |
318 | * Check to see if the necessary fragments are available, and | |
319 | * if they are, allocate them. | |
320 | */ | |
07670f7d | 321 | daddr_t |
f7287e4b KM |
322 | fragextend(ip, cg, bprev, osize, nsize) |
323 | struct inode *ip; | |
07670f7d | 324 | int cg; |
f3c028b7 | 325 | long bprev; |
07670f7d KM |
326 | int osize, nsize; |
327 | { | |
f7287e4b | 328 | register struct fs *fs; |
f3c028b7 KM |
329 | register struct buf *bp; |
330 | register struct cg *cgp; | |
331 | long bno; | |
332 | int frags, bbase; | |
07670f7d KM |
333 | int i; |
334 | ||
f7287e4b | 335 | fs = ip->i_fs; |
d995d89d KM |
336 | frags = numfrags(fs, nsize); |
337 | bbase = fragoff(fs, bprev); | |
b6407c9d | 338 | if (bbase > (bprev + frags - 1) % fs->fs_frag) { |
f3c028b7 | 339 | /* cannot extend across a block boundry */ |
ae851115 | 340 | return (NULL); |
f3c028b7 | 341 | } |
f7287e4b | 342 | bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); |
d995d89d KM |
343 | if (bp->b_flags & B_ERROR) { |
344 | brelse(bp); | |
ae851115 | 345 | return (NULL); |
d995d89d | 346 | } |
07670f7d | 347 | cgp = bp->b_un.b_cg; |
6994bf5d | 348 | bno = dtogd(fs, bprev); |
d995d89d | 349 | for (i = numfrags(fs, osize); i < frags; i++) |
aca50d72 KM |
350 | if (isclr(cgp->cg_free, bno + i)) { |
351 | brelse(bp); | |
ae851115 | 352 | return (NULL); |
aca50d72 KM |
353 | } |
354 | /* | |
355 | * the current fragment can be extended | |
356 | * deduct the count on fragment being extended into | |
357 | * increase the count on the remaining fragment (if any) | |
358 | * allocate the extended piece | |
359 | */ | |
360 | for (i = frags; i < fs->fs_frag - bbase; i++) | |
f3c028b7 KM |
361 | if (isclr(cgp->cg_free, bno + i)) |
362 | break; | |
d995d89d | 363 | cgp->cg_frsum[i - numfrags(fs, osize)]--; |
aca50d72 KM |
364 | if (i != frags) |
365 | cgp->cg_frsum[i - frags]++; | |
d995d89d | 366 | for (i = numfrags(fs, osize); i < frags; i++) { |
aca50d72 KM |
367 | clrbit(cgp->cg_free, bno + i); |
368 | cgp->cg_cs.cs_nffree--; | |
369 | fs->fs_cstotal.cs_nffree--; | |
370 | fs->fs_cs(fs, cg).cs_nffree--; | |
f3c028b7 | 371 | } |
aca50d72 KM |
372 | fs->fs_fmod++; |
373 | bdwrite(bp); | |
374 | return (bprev); | |
07670f7d KM |
375 | } |
376 | ||
502770a3 KM |
377 | /* |
378 | * Determine whether a block can be allocated. | |
379 | * | |
380 | * Check to see if a block of the apprpriate size is available, | |
381 | * and if it is, allocate it. | |
382 | */ | |
e3fe2d69 | 383 | daddr_t |
f7287e4b KM |
384 | alloccg(ip, cg, bpref, size) |
385 | struct inode *ip; | |
e3fe2d69 KM |
386 | int cg; |
387 | daddr_t bpref; | |
388 | int size; | |
389 | { | |
f7287e4b | 390 | register struct fs *fs; |
f3c028b7 KM |
391 | register struct buf *bp; |
392 | register struct cg *cgp; | |
393 | int bno, frags; | |
394 | int allocsiz; | |
f3c028b7 | 395 | register int i; |
e3fe2d69 | 396 | |
f7287e4b | 397 | fs = ip->i_fs; |
b6407c9d | 398 | if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize) |
ae851115 | 399 | return (NULL); |
f7287e4b | 400 | bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); |
d995d89d KM |
401 | if (bp->b_flags & B_ERROR) { |
402 | brelse(bp); | |
ae851115 | 403 | return (NULL); |
d995d89d | 404 | } |
e3fe2d69 | 405 | cgp = bp->b_un.b_cg; |
b6407c9d | 406 | if (size == fs->fs_bsize) { |
daaf7bee | 407 | bno = alloccgblk(fs, cgp, bpref); |
f3c028b7 KM |
408 | bdwrite(bp); |
409 | return (bno); | |
410 | } | |
411 | /* | |
412 | * check to see if any fragments are already available | |
413 | * allocsiz is the size which will be allocated, hacking | |
414 | * it down to a smaller size if necessary | |
415 | */ | |
d995d89d | 416 | frags = numfrags(fs, size); |
b6407c9d | 417 | for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++) |
f3c028b7 KM |
418 | if (cgp->cg_frsum[allocsiz] != 0) |
419 | break; | |
b6407c9d | 420 | if (allocsiz == fs->fs_frag) { |
f3c028b7 KM |
421 | /* |
422 | * no fragments were available, so a block will be | |
423 | * allocated, and hacked up | |
424 | */ | |
0947395d | 425 | if (cgp->cg_cs.cs_nbfree == 0) { |
f3c028b7 | 426 | brelse(bp); |
ae851115 | 427 | return (NULL); |
f3c028b7 | 428 | } |
daaf7bee | 429 | bno = alloccgblk(fs, cgp, bpref); |
6994bf5d | 430 | bpref = dtogd(fs, bno); |
b6407c9d | 431 | for (i = frags; i < fs->fs_frag; i++) |
f3c028b7 | 432 | setbit(cgp->cg_free, bpref + i); |
b6407c9d | 433 | i = fs->fs_frag - frags; |
0947395d KM |
434 | cgp->cg_cs.cs_nffree += i; |
435 | fs->fs_cstotal.cs_nffree += i; | |
b6407c9d | 436 | fs->fs_cs(fs, cg).cs_nffree += i; |
f3c028b7 KM |
437 | cgp->cg_frsum[i]++; |
438 | bdwrite(bp); | |
439 | return (bno); | |
440 | } | |
743f1ef7 KM |
441 | bno = mapsearch(fs, cgp, bpref, allocsiz); |
442 | if (bno == 0) | |
ae851115 | 443 | return (NULL); |
f3c028b7 KM |
444 | for (i = 0; i < frags; i++) |
445 | clrbit(cgp->cg_free, bno + i); | |
0947395d KM |
446 | cgp->cg_cs.cs_nffree -= frags; |
447 | fs->fs_cstotal.cs_nffree -= frags; | |
b6407c9d | 448 | fs->fs_cs(fs, cg).cs_nffree -= frags; |
f3c028b7 KM |
449 | cgp->cg_frsum[allocsiz]--; |
450 | if (frags != allocsiz) | |
451 | cgp->cg_frsum[allocsiz - frags]++; | |
452 | bdwrite(bp); | |
453 | return (cg * fs->fs_fpg + bno); | |
454 | } | |
455 | ||
502770a3 KM |
456 | /* |
457 | * Allocate a block in a cylinder group. | |
458 | * | |
459 | * This algorithm implements the following policy: | |
460 | * 1) allocate the requested block. | |
461 | * 2) allocate a rotationally optimal block in the same cylinder. | |
462 | * 3) allocate the next available block on the block rotor for the | |
463 | * specified cylinder group. | |
464 | * Note that this routine only allocates fs_bsize blocks; these | |
465 | * blocks may be fragmented by the routine that allocates them. | |
466 | */ | |
f3c028b7 | 467 | daddr_t |
daaf7bee | 468 | alloccgblk(fs, cgp, bpref) |
f7287e4b | 469 | register struct fs *fs; |
f3c028b7 KM |
470 | register struct cg *cgp; |
471 | daddr_t bpref; | |
472 | { | |
743f1ef7 | 473 | daddr_t bno; |
ae851115 | 474 | int cylno, pos, delta; |
743f1ef7 | 475 | short *cylbp; |
aca50d72 | 476 | register int i; |
f3c028b7 | 477 | |
743f1ef7 KM |
478 | if (bpref == 0) { |
479 | bpref = cgp->cg_rotor; | |
aca50d72 KM |
480 | goto norot; |
481 | } | |
482 | bpref &= ~(fs->fs_frag - 1); | |
6994bf5d | 483 | bpref = dtogd(fs, bpref); |
aca50d72 KM |
484 | /* |
485 | * if the requested block is available, use it | |
486 | */ | |
487 | if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) { | |
488 | bno = bpref; | |
489 | goto gotit; | |
490 | } | |
aca50d72 KM |
491 | /* |
492 | * check for a block available on the same cylinder | |
aca50d72 KM |
493 | */ |
494 | cylno = cbtocylno(fs, bpref); | |
502770a3 KM |
495 | if (cgp->cg_btot[cylno] == 0) |
496 | goto norot; | |
497 | if (fs->fs_cpc == 0) { | |
498 | /* | |
499 | * block layout info is not available, so just have | |
500 | * to take any block in this cylinder. | |
501 | */ | |
502 | bpref = howmany(fs->fs_spc * cylno, NSPF(fs)); | |
503 | goto norot; | |
504 | } | |
505 | /* | |
506 | * find a block that is rotationally optimal | |
507 | */ | |
aca50d72 KM |
508 | cylbp = cgp->cg_b[cylno]; |
509 | if (fs->fs_rotdelay == 0) { | |
510 | pos = cbtorpos(fs, bpref); | |
743f1ef7 | 511 | } else { |
743f1ef7 | 512 | /* |
aca50d72 KM |
513 | * here we convert ms of delay to frags as: |
514 | * (frags) = (ms) * (rev/sec) * (sect/rev) / | |
515 | * ((sect/frag) * (ms/sec)) | |
516 | * then round up to the next rotational position | |
743f1ef7 | 517 | */ |
aca50d72 KM |
518 | bpref += fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect / |
519 | (NSPF(fs) * 1000); | |
520 | pos = cbtorpos(fs, bpref); | |
521 | pos = (pos + 1) % NRPOS; | |
522 | } | |
523 | /* | |
524 | * check the summary information to see if a block is | |
525 | * available in the requested cylinder starting at the | |
526 | * optimal rotational position and proceeding around. | |
527 | */ | |
528 | for (i = pos; i < NRPOS; i++) | |
529 | if (cylbp[i] > 0) | |
530 | break; | |
531 | if (i == NRPOS) | |
532 | for (i = 0; i < pos; i++) | |
743f1ef7 KM |
533 | if (cylbp[i] > 0) |
534 | break; | |
aca50d72 KM |
535 | if (cylbp[i] > 0) { |
536 | /* | |
537 | * found a rotational position, now find the actual | |
538 | * block. A panic if none is actually there. | |
539 | */ | |
540 | pos = cylno % fs->fs_cpc; | |
541 | bno = (cylno - pos) * fs->fs_spc / NSPB(fs); | |
542 | if (fs->fs_postbl[pos][i] == -1) | |
543 | panic("alloccgblk: cyl groups corrupted"); | |
ae851115 | 544 | for (i = fs->fs_postbl[pos][i];; ) { |
aca50d72 KM |
545 | if (isblock(fs, cgp->cg_free, bno + i)) { |
546 | bno = (bno + i) * fs->fs_frag; | |
547 | goto gotit; | |
743f1ef7 | 548 | } |
ae851115 KM |
549 | delta = fs->fs_rotbl[i]; |
550 | if (delta <= 0 || delta > MAXBPC - i) | |
aca50d72 | 551 | break; |
ae851115 | 552 | i += delta; |
743f1ef7 | 553 | } |
aca50d72 | 554 | panic("alloccgblk: can't find blk in cyl"); |
e3fe2d69 | 555 | } |
aca50d72 KM |
556 | norot: |
557 | /* | |
558 | * no blocks in the requested cylinder, so take next | |
559 | * available one in this cylinder group. | |
560 | */ | |
b6407c9d | 561 | bno = mapsearch(fs, cgp, bpref, fs->fs_frag); |
743f1ef7 | 562 | if (bno == 0) |
ae851115 | 563 | return (NULL); |
743f1ef7 | 564 | cgp->cg_rotor = bno; |
e3fe2d69 | 565 | gotit: |
b6407c9d | 566 | clrblock(fs, cgp->cg_free, bno/fs->fs_frag); |
0947395d KM |
567 | cgp->cg_cs.cs_nbfree--; |
568 | fs->fs_cstotal.cs_nbfree--; | |
b6407c9d | 569 | fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; |
502770a3 KM |
570 | cylno = cbtocylno(fs, bno); |
571 | cgp->cg_b[cylno][cbtorpos(fs, bno)]--; | |
572 | cgp->cg_btot[cylno]--; | |
e3fe2d69 | 573 | fs->fs_fmod++; |
743f1ef7 | 574 | return (cgp->cg_cgx * fs->fs_fpg + bno); |
e3fe2d69 KM |
575 | } |
576 | ||
502770a3 KM |
577 | /* |
578 | * Determine whether an inode can be allocated. | |
579 | * | |
580 | * Check to see if an inode is available, and if it is, | |
581 | * allocate it using the following policy: | |
582 | * 1) allocate the requested inode. | |
583 | * 2) allocate the next available inode after the requested | |
584 | * inode in the specified cylinder group. | |
585 | */ | |
daaf7bee | 586 | ino_t |
f7287e4b KM |
587 | ialloccg(ip, cg, ipref, mode) |
588 | struct inode *ip; | |
e3fe2d69 KM |
589 | int cg; |
590 | daddr_t ipref; | |
591 | int mode; | |
592 | { | |
f7287e4b | 593 | register struct fs *fs; |
f3c028b7 KM |
594 | register struct buf *bp; |
595 | register struct cg *cgp; | |
e3fe2d69 KM |
596 | int i; |
597 | ||
f7287e4b | 598 | fs = ip->i_fs; |
b6407c9d | 599 | if (fs->fs_cs(fs, cg).cs_nifree == 0) |
ae851115 | 600 | return (NULL); |
f7287e4b | 601 | bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); |
d995d89d KM |
602 | if (bp->b_flags & B_ERROR) { |
603 | brelse(bp); | |
ae851115 | 604 | return (NULL); |
d995d89d | 605 | } |
e3fe2d69 | 606 | cgp = bp->b_un.b_cg; |
e3fe2d69 KM |
607 | if (ipref) { |
608 | ipref %= fs->fs_ipg; | |
609 | if (isclr(cgp->cg_iused, ipref)) | |
610 | goto gotit; | |
611 | } else | |
612 | ipref = cgp->cg_irotor; | |
613 | for (i = 0; i < fs->fs_ipg; i++) { | |
614 | ipref++; | |
615 | if (ipref >= fs->fs_ipg) | |
616 | ipref = 0; | |
617 | if (isclr(cgp->cg_iused, ipref)) { | |
618 | cgp->cg_irotor = ipref; | |
619 | goto gotit; | |
620 | } | |
621 | } | |
622 | brelse(bp); | |
ae851115 | 623 | return (NULL); |
e3fe2d69 KM |
624 | gotit: |
625 | setbit(cgp->cg_iused, ipref); | |
0947395d KM |
626 | cgp->cg_cs.cs_nifree--; |
627 | fs->fs_cstotal.cs_nifree--; | |
b6407c9d | 628 | fs->fs_cs(fs, cg).cs_nifree--; |
e3fe2d69 KM |
629 | fs->fs_fmod++; |
630 | if ((mode & IFMT) == IFDIR) { | |
0947395d KM |
631 | cgp->cg_cs.cs_ndir++; |
632 | fs->fs_cstotal.cs_ndir++; | |
b6407c9d | 633 | fs->fs_cs(fs, cg).cs_ndir++; |
e3fe2d69 KM |
634 | } |
635 | bdwrite(bp); | |
636 | return (cg * fs->fs_ipg + ipref); | |
637 | } | |
638 | ||
502770a3 KM |
639 | /* |
640 | * Free a block or fragment. | |
641 | * | |
642 | * The specified block or fragment is placed back in the | |
643 | * free map. If a fragment is deallocated, a possible | |
644 | * block reassembly is checked. | |
645 | */ | |
f7287e4b KM |
646 | fre(ip, bno, size) |
647 | register struct inode *ip; | |
e3fe2d69 | 648 | daddr_t bno; |
daaf7bee | 649 | off_t size; |
e3fe2d69 KM |
650 | { |
651 | register struct fs *fs; | |
652 | register struct cg *cgp; | |
653 | register struct buf *bp; | |
f3c028b7 KM |
654 | int cg, blk, frags, bbase; |
655 | register int i; | |
e3fe2d69 | 656 | |
f7287e4b | 657 | fs = ip->i_fs; |
d995d89d | 658 | if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) |
b6407c9d | 659 | panic("free: bad size"); |
6994bf5d | 660 | cg = dtog(fs, bno); |
e3fe2d69 KM |
661 | if (badblock(fs, bno)) |
662 | return; | |
f7287e4b | 663 | bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); |
d995d89d KM |
664 | if (bp->b_flags & B_ERROR) { |
665 | brelse(bp); | |
e3fe2d69 | 666 | return; |
d995d89d | 667 | } |
e3fe2d69 | 668 | cgp = bp->b_un.b_cg; |
6994bf5d | 669 | bno = dtogd(fs, bno); |
b6407c9d KM |
670 | if (size == fs->fs_bsize) { |
671 | if (isblock(fs, cgp->cg_free, bno/fs->fs_frag)) | |
07670f7d | 672 | panic("free: freeing free block"); |
b6407c9d | 673 | setblock(fs, cgp->cg_free, bno/fs->fs_frag); |
0947395d KM |
674 | cgp->cg_cs.cs_nbfree++; |
675 | fs->fs_cstotal.cs_nbfree++; | |
b6407c9d | 676 | fs->fs_cs(fs, cg).cs_nbfree++; |
502770a3 KM |
677 | i = cbtocylno(fs, bno); |
678 | cgp->cg_b[i][cbtorpos(fs, bno)]++; | |
679 | cgp->cg_btot[i]++; | |
07670f7d | 680 | } else { |
b6407c9d | 681 | bbase = bno - (bno % fs->fs_frag); |
f3c028b7 KM |
682 | /* |
683 | * decrement the counts associated with the old frags | |
684 | */ | |
ae851115 | 685 | blk = blkmap(fs, cgp->cg_free, bbase); |
b6407c9d | 686 | fragacct(fs, blk, cgp->cg_frsum, -1); |
f3c028b7 KM |
687 | /* |
688 | * deallocate the fragment | |
689 | */ | |
d995d89d | 690 | frags = numfrags(fs, size); |
f3c028b7 | 691 | for (i = 0; i < frags; i++) { |
07670f7d KM |
692 | if (isset(cgp->cg_free, bno + i)) |
693 | panic("free: freeing free frag"); | |
694 | setbit(cgp->cg_free, bno + i); | |
07670f7d | 695 | } |
ae851115 KM |
696 | cgp->cg_cs.cs_nffree += i; |
697 | fs->fs_cstotal.cs_nffree += i; | |
698 | fs->fs_cs(fs, cg).cs_nffree += i; | |
f3c028b7 KM |
699 | /* |
700 | * add back in counts associated with the new frags | |
701 | */ | |
ae851115 | 702 | blk = blkmap(fs, cgp->cg_free, bbase); |
b6407c9d | 703 | fragacct(fs, blk, cgp->cg_frsum, 1); |
f3c028b7 KM |
704 | /* |
705 | * if a complete block has been reassembled, account for it | |
706 | */ | |
b6407c9d KM |
707 | if (isblock(fs, cgp->cg_free, bbase / fs->fs_frag)) { |
708 | cgp->cg_cs.cs_nffree -= fs->fs_frag; | |
709 | fs->fs_cstotal.cs_nffree -= fs->fs_frag; | |
710 | fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; | |
0947395d KM |
711 | cgp->cg_cs.cs_nbfree++; |
712 | fs->fs_cstotal.cs_nbfree++; | |
b6407c9d | 713 | fs->fs_cs(fs, cg).cs_nbfree++; |
502770a3 KM |
714 | i = cbtocylno(fs, bbase); |
715 | cgp->cg_b[i][cbtorpos(fs, bbase)]++; | |
716 | cgp->cg_btot[i]++; | |
07670f7d KM |
717 | } |
718 | } | |
e3fe2d69 | 719 | fs->fs_fmod++; |
e3fe2d69 KM |
720 | bdwrite(bp); |
721 | } | |
722 | ||
502770a3 KM |
723 | /* |
724 | * Free an inode. | |
725 | * | |
726 | * The specified inode is placed back in the free map. | |
727 | */ | |
f7287e4b KM |
728 | ifree(ip, ino, mode) |
729 | struct inode *ip; | |
e3fe2d69 KM |
730 | ino_t ino; |
731 | int mode; | |
732 | { | |
733 | register struct fs *fs; | |
734 | register struct cg *cgp; | |
735 | register struct buf *bp; | |
e3fe2d69 KM |
736 | int cg; |
737 | ||
f7287e4b | 738 | fs = ip->i_fs; |
e3fe2d69 KM |
739 | if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg) |
740 | panic("ifree: range"); | |
6994bf5d | 741 | cg = itog(fs, ino); |
f7287e4b | 742 | bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); |
d995d89d KM |
743 | if (bp->b_flags & B_ERROR) { |
744 | brelse(bp); | |
e3fe2d69 | 745 | return; |
d995d89d | 746 | } |
e3fe2d69 KM |
747 | cgp = bp->b_un.b_cg; |
748 | ino %= fs->fs_ipg; | |
749 | if (isclr(cgp->cg_iused, ino)) | |
750 | panic("ifree: freeing free inode"); | |
751 | clrbit(cgp->cg_iused, ino); | |
0947395d KM |
752 | cgp->cg_cs.cs_nifree++; |
753 | fs->fs_cstotal.cs_nifree++; | |
b6407c9d | 754 | fs->fs_cs(fs, cg).cs_nifree++; |
e3fe2d69 | 755 | if ((mode & IFMT) == IFDIR) { |
0947395d KM |
756 | cgp->cg_cs.cs_ndir--; |
757 | fs->fs_cstotal.cs_ndir--; | |
b6407c9d | 758 | fs->fs_cs(fs, cg).cs_ndir--; |
e3fe2d69 KM |
759 | } |
760 | fs->fs_fmod++; | |
761 | bdwrite(bp); | |
762 | } | |
763 | ||
743f1ef7 | 764 | /* |
502770a3 KM |
765 | * Find a block of the specified size in the specified cylinder group. |
766 | * | |
743f1ef7 KM |
767 | * It is a panic if a request is made to find a block if none are |
768 | * available. | |
769 | */ | |
770 | daddr_t | |
771 | mapsearch(fs, cgp, bpref, allocsiz) | |
772 | register struct fs *fs; | |
773 | register struct cg *cgp; | |
774 | daddr_t bpref; | |
775 | int allocsiz; | |
776 | { | |
777 | daddr_t bno; | |
778 | int start, len, loc, i; | |
779 | int blk, field, subfield, pos; | |
780 | ||
781 | /* | |
782 | * find the fragment by searching through the free block | |
783 | * map for an appropriate bit pattern | |
784 | */ | |
785 | if (bpref) | |
6994bf5d | 786 | start = dtogd(fs, bpref) / NBBY; |
743f1ef7 KM |
787 | else |
788 | start = cgp->cg_frotor / NBBY; | |
942bd18b | 789 | len = howmany(fs->fs_fpg, NBBY) - start; |
b6407c9d | 790 | loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], |
156b8f82 | 791 | 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); |
743f1ef7 | 792 | if (loc == 0) { |
942bd18b KM |
793 | loc = fs->fs_dblkno / NBBY; |
794 | len = start - loc + 1; | |
795 | start = loc; | |
b6407c9d | 796 | loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], |
156b8f82 | 797 | 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); |
743f1ef7 KM |
798 | if (loc == 0) { |
799 | panic("alloccg: map corrupted"); | |
ae851115 | 800 | return (NULL); |
743f1ef7 KM |
801 | } |
802 | } | |
803 | bno = (start + len - loc) * NBBY; | |
804 | cgp->cg_frotor = bno; | |
805 | /* | |
806 | * found the byte in the map | |
807 | * sift through the bits to find the selected frag | |
808 | */ | |
ae851115 KM |
809 | for (i = bno + NBBY; bno < i; bno += fs->fs_frag) { |
810 | blk = blkmap(fs, cgp->cg_free, bno); | |
743f1ef7 KM |
811 | blk <<= 1; |
812 | field = around[allocsiz]; | |
813 | subfield = inside[allocsiz]; | |
b6407c9d | 814 | for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) { |
ae851115 KM |
815 | if ((blk & field) == subfield) |
816 | return (bno + pos); | |
743f1ef7 KM |
817 | field <<= 1; |
818 | subfield <<= 1; | |
819 | } | |
820 | } | |
821 | panic("alloccg: block not in map"); | |
ae851115 | 822 | return (NULL); |
743f1ef7 KM |
823 | } |
824 | ||
f3c028b7 | 825 | /* |
502770a3 KM |
826 | * Update the frsum fields to reflect addition or deletion |
827 | * of some frags. | |
f3c028b7 | 828 | */ |
b6407c9d KM |
829 | fragacct(fs, fragmap, fraglist, cnt) |
830 | struct fs *fs; | |
1b940b13 | 831 | int fragmap; |
0947395d | 832 | long fraglist[]; |
f3c028b7 KM |
833 | int cnt; |
834 | { | |
835 | int inblk; | |
836 | register int field, subfield; | |
837 | register int siz, pos; | |
838 | ||
b6407c9d | 839 | inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; |
f3c028b7 | 840 | fragmap <<= 1; |
b6407c9d | 841 | for (siz = 1; siz < fs->fs_frag; siz++) { |
156b8f82 | 842 | if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) |
f3c028b7 KM |
843 | continue; |
844 | field = around[siz]; | |
845 | subfield = inside[siz]; | |
b6407c9d | 846 | for (pos = siz; pos <= fs->fs_frag; pos++) { |
f3c028b7 KM |
847 | if ((fragmap & field) == subfield) { |
848 | fraglist[siz] += cnt; | |
849 | pos += siz; | |
850 | field <<= siz; | |
851 | subfield <<= siz; | |
852 | } | |
853 | field <<= 1; | |
854 | subfield <<= 1; | |
855 | } | |
856 | } | |
857 | } | |
858 | ||
502770a3 KM |
859 | /* |
860 | * Check that a specified block number is in range. | |
861 | */ | |
e3fe2d69 KM |
862 | badblock(fs, bn) |
863 | register struct fs *fs; | |
864 | daddr_t bn; | |
865 | { | |
866 | ||
6994bf5d | 867 | if ((unsigned)bn >= fs->fs_size || bn < cgdmin(fs, dtog(fs, bn))) { |
e3fe2d69 KM |
868 | fserr(fs, "bad block"); |
869 | return (1); | |
870 | } | |
871 | return (0); | |
872 | } | |
873 | ||
874 | /* | |
502770a3 KM |
875 | * Getfs maps a device number into a pointer to the incore super block. |
876 | * | |
877 | * The algorithm is a linear search through the mount table. A | |
878 | * consistency check of the super block magic number is performed. | |
e3fe2d69 KM |
879 | * |
880 | * panic: no fs -- the device is not mounted. | |
881 | * this "cannot happen" | |
882 | */ | |
883 | struct fs * | |
884 | getfs(dev) | |
885 | dev_t dev; | |
886 | { | |
887 | register struct mount *mp; | |
888 | register struct fs *fs; | |
889 | ||
ae851115 KM |
890 | for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { |
891 | if (mp->m_bufp == NULL || mp->m_dev != dev) | |
892 | continue; | |
893 | fs = mp->m_bufp->b_un.b_fs; | |
894 | if (fs->fs_magic != FS_MAGIC) | |
895 | panic("getfs: bad magic"); | |
896 | return (fs); | |
897 | } | |
e3fe2d69 KM |
898 | panic("getfs: no fs"); |
899 | return (NULL); | |
900 | } | |
901 | ||
902 | /* | |
502770a3 KM |
903 | * Fserr prints the name of a file system with an error diagnostic. |
904 | * | |
905 | * The form of the error message is: | |
e3fe2d69 KM |
906 | * fs: error message |
907 | */ | |
908 | fserr(fs, cp) | |
909 | struct fs *fs; | |
910 | char *cp; | |
911 | { | |
912 | ||
913 | printf("%s: %s\n", fs->fs_fsmnt, cp); | |
914 | } | |
915 | ||
916 | /* | |
917 | * Getfsx returns the index in the file system | |
918 | * table of the specified device. The swap device | |
919 | * is also assigned a pseudo-index. The index may | |
920 | * be used as a compressed indication of the location | |
921 | * of a block, recording | |
922 | * <getfsx(dev),blkno> | |
923 | * rather than | |
924 | * <dev, blkno> | |
925 | * provided the information need remain valid only | |
926 | * as long as the file system is mounted. | |
927 | */ | |
928 | getfsx(dev) | |
929 | dev_t dev; | |
930 | { | |
931 | register struct mount *mp; | |
932 | ||
933 | if (dev == swapdev) | |
934 | return (MSWAPX); | |
935 | for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) | |
936 | if (mp->m_dev == dev) | |
937 | return (mp - &mount[0]); | |
938 | return (-1); | |
939 | } | |
940 | ||
941 | /* | |
942 | * Update is the internal name of 'sync'. It goes through the disk | |
943 | * queues to initiate sandbagged IO; goes through the inodes to write | |
502770a3 KM |
944 | * modified nodes; and it goes through the mount table to initiate |
945 | * the writing of the modified super blocks. | |
e3fe2d69 | 946 | */ |
ae851115 KM |
947 | update(flag) |
948 | int flag; | |
e3fe2d69 KM |
949 | { |
950 | register struct inode *ip; | |
951 | register struct mount *mp; | |
952 | register struct buf *bp; | |
953 | struct fs *fs; | |
743f1ef7 | 954 | int i, blks; |
e3fe2d69 KM |
955 | |
956 | if (updlock) | |
957 | return; | |
958 | updlock++; | |
959 | /* | |
960 | * Write back modified superblocks. | |
961 | * Consistency check that the superblock | |
962 | * of each file system is still in the buffer cache. | |
963 | */ | |
ae851115 KM |
964 | for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { |
965 | if (mp->m_bufp == NULL) | |
966 | continue; | |
967 | fs = mp->m_bufp->b_un.b_fs; | |
968 | if (fs->fs_fmod == 0) | |
969 | continue; | |
970 | if (fs->fs_ronly != 0) | |
971 | panic("update: rofs mod"); | |
972 | bp = getblk(mp->m_dev, SBLOCK, SBSIZE); | |
973 | fs->fs_fmod = 0; | |
ce29a78b | 974 | fs->fs_time = time; |
ae851115 KM |
975 | if (bp->b_un.b_fs != fs) |
976 | panic("update: bad b_fs"); | |
977 | bwrite(bp); | |
978 | blks = howmany(fs->fs_cssize, fs->fs_bsize); | |
979 | for (i = 0; i < blks; i++) { | |
980 | bp = getblk(mp->m_dev, | |
981 | fsbtodb(fs, fs->fs_csaddr + (i * fs->fs_frag)), | |
982 | fs->fs_bsize); | |
e3fe2d69 | 983 | bwrite(bp); |
e3fe2d69 | 984 | } |
ae851115 | 985 | } |
e3fe2d69 KM |
986 | /* |
987 | * Write back each (modified) inode. | |
988 | */ | |
ae851115 KM |
989 | for (ip = inode; ip < inodeNINODE; ip++) { |
990 | if ((ip->i_flag & ILOCK) != 0 || ip->i_count == 0) | |
991 | continue; | |
992 | ip->i_flag |= ILOCK; | |
993 | ip->i_count++; | |
ce29a78b | 994 | iupdat(ip, &time, &time, 0); |
ae851115 KM |
995 | iput(ip); |
996 | } | |
e3fe2d69 KM |
997 | updlock = 0; |
998 | /* | |
999 | * Force stale buffer cache information to be flushed, | |
1000 | * for all devices. | |
1001 | */ | |
1002 | bflush(NODEV); | |
1003 | } | |
b6407c9d KM |
1004 | |
1005 | /* | |
502770a3 KM |
1006 | * block operations |
1007 | * | |
1008 | * check if a block is available | |
b6407c9d | 1009 | */ |
b6407c9d KM |
1010 | isblock(fs, cp, h) |
1011 | struct fs *fs; | |
1012 | unsigned char *cp; | |
1013 | int h; | |
1014 | { | |
1015 | unsigned char mask; | |
1016 | ||
1017 | switch (fs->fs_frag) { | |
1018 | case 8: | |
1019 | return (cp[h] == 0xff); | |
1020 | case 4: | |
1021 | mask = 0x0f << ((h & 0x1) << 2); | |
1022 | return ((cp[h >> 1] & mask) == mask); | |
1023 | case 2: | |
1024 | mask = 0x03 << ((h & 0x3) << 1); | |
1025 | return ((cp[h >> 2] & mask) == mask); | |
1026 | case 1: | |
1027 | mask = 0x01 << (h & 0x7); | |
1028 | return ((cp[h >> 3] & mask) == mask); | |
1029 | default: | |
ae851115 KM |
1030 | panic("isblock"); |
1031 | return (NULL); | |
b6407c9d KM |
1032 | } |
1033 | } | |
502770a3 KM |
1034 | |
1035 | /* | |
1036 | * take a block out of the map | |
1037 | */ | |
b6407c9d KM |
1038 | clrblock(fs, cp, h) |
1039 | struct fs *fs; | |
1040 | unsigned char *cp; | |
1041 | int h; | |
1042 | { | |
1043 | switch ((fs)->fs_frag) { | |
1044 | case 8: | |
1045 | cp[h] = 0; | |
1046 | return; | |
1047 | case 4: | |
1048 | cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); | |
1049 | return; | |
1050 | case 2: | |
1051 | cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); | |
1052 | return; | |
1053 | case 1: | |
1054 | cp[h >> 3] &= ~(0x01 << (h & 0x7)); | |
1055 | return; | |
1056 | default: | |
ae851115 | 1057 | panic("clrblock"); |
b6407c9d KM |
1058 | return; |
1059 | } | |
1060 | } | |
502770a3 KM |
1061 | |
1062 | /* | |
1063 | * put a block into the map | |
1064 | */ | |
b6407c9d KM |
1065 | setblock(fs, cp, h) |
1066 | struct fs *fs; | |
1067 | unsigned char *cp; | |
1068 | int h; | |
1069 | { | |
1070 | switch (fs->fs_frag) { | |
1071 | case 8: | |
1072 | cp[h] = 0xff; | |
1073 | return; | |
1074 | case 4: | |
1075 | cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); | |
1076 | return; | |
1077 | case 2: | |
1078 | cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); | |
1079 | return; | |
1080 | case 1: | |
1081 | cp[h >> 3] |= (0x01 << (h & 0x7)); | |
1082 | return; | |
1083 | default: | |
ae851115 | 1084 | panic("setblock"); |
b6407c9d KM |
1085 | return; |
1086 | } | |
1087 | } |