lint
[unix-history] / usr / src / sys / ufs / ffs / ffs_alloc.c
CommitLineData
da7c5cc6 1/*
7188ac27 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
202a4bd9 3 * All rights reserved.
da7c5cc6 4 *
b702c21d 5 * %sccs.include.redist.c%
202a4bd9 6 *
80e9de4e 7 * @(#)ffs_alloc.c 7.33 (Berkeley) %G%
da7c5cc6 8 */
e3fe2d69 9
6d3d8a1c
KB
10#include <sys/param.h>
11#include <sys/systm.h>
12#include <sys/buf.h>
13#include <sys/proc.h>
14#include <sys/vnode.h>
15#include <sys/kernel.h>
16#include <sys/syslog.h>
c6f5111d 17
80e9de4e
KM
18#include <vm/vm.h>
19
6d3d8a1c
KB
20#include <ufs/ufs/quota.h>
21#include <ufs/ufs/inode.h>
e3fe2d69 22
6d3d8a1c
KB
23#include <ufs/ffs/fs.h>
24#include <ufs/ffs/ffs_extern.h>
25
26extern u_long nextgennumber;
27
28static daddr_t ffs_alloccg __P((struct inode *, int, daddr_t, int));
29static daddr_t ffs_alloccgblk __P((struct fs *, struct cg *, daddr_t));
30static ino_t ffs_dirpref __P((struct fs *));
31static daddr_t ffs_fragextend __P((struct inode *, int, long, int, int));
32static void ffs_fserr __P((struct fs *, u_int, char *));
33static u_long ffs_hashalloc
34 __P((struct inode *, int, long, int, u_long (*)()));
35static ino_t ffs_ialloccg __P((struct inode *, int, daddr_t, int));
36static daddr_t ffs_mapsearch __P((struct fs *, struct cg *, daddr_t, int));
e3fe2d69 37
502770a3
KM
38/*
39 * Allocate a block in the file system.
40 *
41 * The size of the requested block is given, which must be some
42 * multiple of fs_fsize and <= fs_bsize.
43 * A preference may be optionally specified. If a preference is given
44 * the following hierarchy is used to allocate a block:
45 * 1) allocate the requested block.
46 * 2) allocate a rotationally optimal block in the same cylinder.
47 * 3) allocate a block in the same cylinder group.
48 * 4) quadradically rehash into other cylinder groups, until an
49 * available block is located.
50 * If no block preference is given the following heirarchy is used
51 * to allocate a block:
52 * 1) allocate a block in the cylinder group that contains the
53 * inode for the file.
54 * 2) quadradically rehash into other cylinder groups, until an
55 * available block is located.
56 */
9438887a 57ffs_alloc(ip, lbn, bpref, size, cred, bnp)
f3c028b7 58 register struct inode *ip;
0c36425b 59 daddr_t lbn, bpref;
e3fe2d69 60 int size;
9438887a 61 struct ucred *cred;
0c36425b 62 daddr_t *bnp;
e3fe2d69
KM
63{
64 daddr_t bno;
65 register struct fs *fs;
f3c028b7 66 register struct buf *bp;
7188ac27 67 int cg, error;
e3fe2d69 68
0c36425b 69 *bnp = 0;
f7287e4b 70 fs = ip->i_fs;
9438887a 71#ifdef DIAGNOSTIC
ffd90e52
KM
72 if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) {
73 printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n",
74 ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt);
6d3d8a1c 75 panic("ffs_alloc: bad size");
ffd90e52 76 }
9438887a
KM
77 if (cred == NOCRED)
78 panic("ffs_alloc: missing credential\n");
79#endif /* DIAGNOSTIC */
b6407c9d 80 if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0)
0947395d 81 goto nospace;
00bff950 82 if (cred->cr_uid != 0 && freespace(fs, fs->fs_minfree) <= 0)
e3fe2d69 83 goto nospace;
b4567e9c 84#ifdef QUOTA
00bff950 85 if (error = chkdq(ip, (long)btodb(size), cred, 0))
7188ac27 86 return (error);
ca90a6bf 87#endif
260e5e3c
KM
88 if (bpref >= fs->fs_size)
89 bpref = 0;
e3fe2d69 90 if (bpref == 0)
6994bf5d 91 cg = itog(fs, ip->i_number);
e3fe2d69 92 else
6994bf5d 93 cg = dtog(fs, bpref);
6d3d8a1c
KB
94 bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, size,
95 (u_long (*)())ffs_alloccg);
0c36425b
KM
96 if (bno > 0) {
97 ip->i_blocks += btodb(size);
98 ip->i_flag |= IUPD|ICHG;
99 *bnp = bno;
100 return (0);
101 }
8a403f0d
KM
102#ifdef QUOTA
103 /*
104 * Restore user's disk quota because allocation failed.
105 */
106 (void) chkdq(ip, (long)-btodb(size), cred, FORCE);
107#endif
e3fe2d69 108nospace:
6d3d8a1c 109 ffs_fserr(fs, cred->cr_uid, "file system full");
e3fe2d69 110 uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
7188ac27 111 return (ENOSPC);
e3fe2d69
KM
112}
113
502770a3
KM
114/*
115 * Reallocate a fragment to a bigger size
116 *
117 * The number and size of the old block is given, and a preference
118 * and new size is also specified. The allocator attempts to extend
119 * the original block. Failing that, the regular block allocator is
120 * invoked to get an appropriate block.
121 */
9438887a 122ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp)
f7287e4b 123 register struct inode *ip;
31cd85c7 124 daddr_t lbprev;
0c36425b 125 daddr_t bpref;
07670f7d 126 int osize, nsize;
9438887a 127 struct ucred *cred;
7188ac27 128 struct buf **bpp;
07670f7d 129{
07670f7d 130 register struct fs *fs;
7188ac27 131 struct buf *bp, *obp;
8986c97c
KM
132 int cg, request, error;
133 daddr_t bprev, bno;
07670f7d 134
7188ac27 135 *bpp = 0;
f7287e4b 136 fs = ip->i_fs;
9438887a 137#ifdef DIAGNOSTIC
d995d89d 138 if ((unsigned)osize > fs->fs_bsize || fragoff(fs, osize) != 0 ||
ffd90e52 139 (unsigned)nsize > fs->fs_bsize || fragoff(fs, nsize) != 0) {
6d3d8a1c
KB
140 printf(
141 "dev = 0x%x, bsize = %d, osize = %d, nsize = %d, fs = %s\n",
ffd90e52 142 ip->i_dev, fs->fs_bsize, osize, nsize, fs->fs_fsmnt);
6d3d8a1c 143 panic("ffs_realloccg: bad size");
ffd90e52 144 }
9438887a
KM
145 if (cred == NOCRED)
146 panic("ffs_realloccg: missing credential\n");
147#endif /* DIAGNOSTIC */
00bff950 148 if (cred->cr_uid != 0 && freespace(fs, fs->fs_minfree) <= 0)
0947395d 149 goto nospace;
0c36425b 150 if ((bprev = ip->i_db[lbprev]) == 0) {
ffd90e52
KM
151 printf("dev = 0x%x, bsize = %d, bprev = %d, fs = %s\n",
152 ip->i_dev, fs->fs_bsize, bprev, fs->fs_fsmnt);
6d3d8a1c 153 panic("ffs_realloccg: bad bprev");
ffd90e52 154 }
0c36425b
KM
155 /*
156 * Allocate the extra space in the buffer.
157 */
158 if (error = bread(ITOV(ip), lbprev, osize, NOCRED, &bp)) {
159 brelse(bp);
160 return (error);
161 }
8a403f0d
KM
162#ifdef QUOTA
163 if (error = chkdq(ip, (long)btodb(nsize - osize), cred, 0)) {
164 brelse(bp);
165 return (error);
166 }
167#endif
0c36425b
KM
168 /*
169 * Check for extension in the existing location.
170 */
ae851115 171 cg = dtog(fs, bprev);
6d3d8a1c 172 if (bno = ffs_fragextend(ip, cg, (long)bprev, osize, nsize)) {
72ef728e 173 if (bp->b_blkno != fsbtodb(fs, bno))
0c36425b 174 panic("bad blockno");
2393702a
KM
175 ip->i_blocks += btodb(nsize - osize);
176 ip->i_flag |= IUPD|ICHG;
b3f3adbd
KM
177 allocbuf(bp, nsize);
178 bp->b_flags |= B_DONE;
179 bzero(bp->b_un.b_addr + osize, (unsigned)nsize - osize);
7188ac27
KM
180 *bpp = bp;
181 return (0);
f3c028b7 182 }
0c36425b
KM
183 /*
184 * Allocate a new disk location.
185 */
260e5e3c
KM
186 if (bpref >= fs->fs_size)
187 bpref = 0;
aec7dd3b 188 switch ((int)fs->fs_optim) {
f8484b5f
KM
189 case FS_OPTSPACE:
190 /*
191 * Allocate an exact sized fragment. Although this makes
192 * best use of space, we will waste time relocating it if
193 * the file continues to grow. If the fragmentation is
194 * less than half of the minimum free reserve, we choose
195 * to begin optimizing for time.
196 */
f7fa0c54 197 request = nsize;
f8484b5f
KM
198 if (fs->fs_minfree < 5 ||
199 fs->fs_cstotal.cs_nffree >
200 fs->fs_dsize * fs->fs_minfree / (2 * 100))
201 break;
202 log(LOG_NOTICE, "%s: optimization changed from SPACE to TIME\n",
203 fs->fs_fsmnt);
204 fs->fs_optim = FS_OPTTIME;
205 break;
206 case FS_OPTTIME:
207 /*
6d3d8a1c
KB
208 * At this point we have discovered a file that is trying to
209 * grow a small fragment to a larger fragment. To save time,
210 * we allocate a full sized block, then free the unused portion.
211 * If the file continues to grow, the `ffs_fragextend' call
212 * above will be able to grow it in place without further
213 * copying. If aberrant programs cause disk fragmentation to
214 * grow within 2% of the free reserve, we choose to begin
215 * optimizing for space.
f8484b5f 216 */
f7fa0c54 217 request = fs->fs_bsize;
f8484b5f
KM
218 if (fs->fs_cstotal.cs_nffree <
219 fs->fs_dsize * (fs->fs_minfree - 2) / 100)
220 break;
221 log(LOG_NOTICE, "%s: optimization changed from TIME to SPACE\n",
222 fs->fs_fsmnt);
223 fs->fs_optim = FS_OPTSPACE;
224 break;
225 default:
226 printf("dev = 0x%x, optim = %d, fs = %s\n",
227 ip->i_dev, fs->fs_optim, fs->fs_fsmnt);
6d3d8a1c 228 panic("ffs_realloccg: bad optim");
f8484b5f
KM
229 /* NOTREACHED */
230 }
6d3d8a1c
KB
231 bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, request,
232 (u_long (*)())ffs_alloccg);
6459ebe0 233 if (bno > 0) {
ec67a3ce
MK
234#ifdef SECSIZE
235 obp = bread(ip->i_dev, fsbtodb(fs, bprev), osize,
236 fs->fs_dbsize);
237#else SECSIZE
ec67a3ce
MK
238 count = howmany(osize, CLBYTES);
239 for (i = 0; i < count; i++)
240#ifdef SECSIZE
241 munhash(ip->i_dev, bn + i * CLBYTES / fs->fs_dbsize);
242#else SECSIZE
243 munhash(ip->i_dev, bn + i * CLBYTES / DEV_BSIZE);
244#endif SECSIZE
31cd85c7 245 ffs_blkfree(ip, bprev, (long)osize);
f7fa0c54 246 if (nsize < request)
6d3d8a1c 247 ffs_blkfree(ip, bno + numfrags(fs, nsize),
31cd85c7 248 (long)(request - nsize));
2523b389
SL
249 ip->i_blocks += btodb(nsize - osize);
250 ip->i_flag |= IUPD|ICHG;
b3f3adbd
KM
251 allocbuf(bp, nsize);
252 bp->b_flags |= B_DONE;
253 bzero(bp->b_un.b_addr + osize, (unsigned)nsize - osize);
7188ac27
KM
254 *bpp = bp;
255 return (0);
f3c028b7 256 }
8a403f0d
KM
257#ifdef QUOTA
258 /*
259 * Restore user's disk quota because allocation failed.
260 */
261 (void) chkdq(ip, (long)-btodb(nsize - osize), cred, FORCE);
262#endif
0c36425b 263 brelse(bp);
0947395d 264nospace:
f3c028b7
KM
265 /*
266 * no space available
267 */
6d3d8a1c 268 ffs_fserr(fs, cred->cr_uid, "file system full");
07670f7d 269 uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
7188ac27 270 return (ENOSPC);
07670f7d
KM
271}
272
502770a3
KM
273/*
274 * Allocate an inode in the file system.
275 *
6d3d8a1c
KB
276 * If allocating a directory, use ffs_dirpref to select the inode.
277 * If allocating in a directory, the following hierarchy is followed:
278 * 1) allocate the preferred inode.
502770a3
KM
279 * 2) allocate an inode in the same cylinder group.
280 * 3) quadradically rehash into other cylinder groups, until an
281 * available inode is located.
282 * If no inode preference is given the following heirarchy is used
283 * to allocate an inode:
284 * 1) allocate an inode in cylinder group 0.
285 * 2) quadradically rehash into other cylinder groups, until an
286 * available inode is located.
287 */
a9013e03
KM
288ffs_valloc(pvp, mode, cred, vpp)
289 register struct vnode *pvp;
e3fe2d69 290 int mode;
00bff950 291 struct ucred *cred;
a9013e03 292 struct vnode **vpp;
e3fe2d69 293{
a9013e03 294 register struct inode *pip;
e3fe2d69
KM
295 register struct fs *fs;
296 register struct inode *ip;
6d3d8a1c 297 ino_t ino, ipref;
7188ac27 298 int cg, error;
e3fe2d69 299
a9013e03
KM
300 *vpp = NULL;
301 pip = VTOI(pvp);
f7287e4b 302 fs = pip->i_fs;
0947395d 303 if (fs->fs_cstotal.cs_nifree == 0)
e3fe2d69 304 goto noinodes;
6d3d8a1c
KB
305
306 if ((mode & IFMT) == IFDIR)
a9013e03 307 ipref = ffs_dirpref(fs);
6d3d8a1c
KB
308 else
309 ipref = pip->i_number;
260e5e3c
KM
310 if (ipref >= fs->fs_ncg * fs->fs_ipg)
311 ipref = 0;
6994bf5d 312 cg = itog(fs, ipref);
6d3d8a1c 313 ino = (ino_t)ffs_hashalloc(pip, cg, (long)ipref, mode, ffs_ialloccg);
e3fe2d69
KM
314 if (ino == 0)
315 goto noinodes;
a9013e03 316 error = ffs_vget(pvp->v_mount, ino, vpp);
7188ac27 317 if (error) {
a9013e03 318 ffs_vfree(pvp, ino, mode);
7188ac27 319 return (error);
e3fe2d69 320 }
a9013e03 321 ip = VTOI(*vpp);
ffd90e52
KM
322 if (ip->i_mode) {
323 printf("mode = 0%o, inum = %d, fs = %s\n",
324 ip->i_mode, ip->i_number, fs->fs_fsmnt);
a9013e03 325 panic("ffs_valloc: dup alloc");
ffd90e52 326 }
2523b389
SL
327 if (ip->i_blocks) { /* XXX */
328 printf("free inode %s/%d had %d blocks\n",
329 fs->fs_fsmnt, ino, ip->i_blocks);
330 ip->i_blocks = 0;
331 }
7e0dee76 332 ip->i_flags = 0;
fb92d0ab
KM
333 /*
334 * Set up a new generation number for this inode.
335 */
336 if (++nextgennumber < (u_long)time.tv_sec)
337 nextgennumber = time.tv_sec;
338 ip->i_gen = nextgennumber;
7188ac27 339 return (0);
e3fe2d69 340noinodes:
6d3d8a1c 341 ffs_fserr(fs, cred->cr_uid, "out of inodes");
ae851115 342 uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt);
7188ac27 343 return (ENOSPC);
e3fe2d69
KM
344}
345
743f1ef7 346/*
502770a3
KM
347 * Find a cylinder to place a directory.
348 *
349 * The policy implemented by this algorithm is to select from
350 * among those cylinder groups with above the average number of
351 * free inodes, the one with the smallest number of directories.
743f1ef7 352 */
6d3d8a1c
KB
353static ino_t
354ffs_dirpref(fs)
e3fe2d69 355 register struct fs *fs;
f7287e4b 356{
743f1ef7 357 int cg, minndir, mincg, avgifree;
e3fe2d69 358
0947395d 359 avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg;
743f1ef7 360 minndir = fs->fs_ipg;
e3fe2d69 361 mincg = 0;
743f1ef7 362 for (cg = 0; cg < fs->fs_ncg; cg++)
b6407c9d
KM
363 if (fs->fs_cs(fs, cg).cs_ndir < minndir &&
364 fs->fs_cs(fs, cg).cs_nifree >= avgifree) {
e3fe2d69 365 mincg = cg;
b6407c9d 366 minndir = fs->fs_cs(fs, cg).cs_ndir;
e3fe2d69 367 }
4f083fd7 368 return ((ino_t)(fs->fs_ipg * mincg));
e3fe2d69
KM
369}
370
743f1ef7 371/*
4f083fd7
SL
372 * Select the desired position for the next block in a file. The file is
373 * logically divided into sections. The first section is composed of the
374 * direct blocks. Each additional section contains fs_maxbpg blocks.
375 *
376 * If no blocks have been allocated in the first section, the policy is to
377 * request a block in the same cylinder group as the inode that describes
378 * the file. If no blocks have been allocated in any other section, the
379 * policy is to place the section in a cylinder group with a greater than
380 * average number of free blocks. An appropriate cylinder group is found
16e7863f
KM
381 * by using a rotor that sweeps the cylinder groups. When a new group of
382 * blocks is needed, the sweep begins in the cylinder group following the
383 * cylinder group from which the previous allocation was made. The sweep
384 * continues until a cylinder group with greater than the average number
385 * of free blocks is found. If the allocation is for the first block in an
386 * indirect block, the information on the previous allocation is unavailable;
387 * here a best guess is made based upon the logical block number being
388 * allocated.
4f083fd7
SL
389 *
390 * If a section is already partially allocated, the policy is to
391 * contiguously allocate fs_maxcontig blocks. The end of one of these
392 * contiguous blocks and the beginning of the next is physically separated
393 * so that the disk head will be in transit between them for at least
394 * fs_rotdelay milliseconds. This is to allow time for the processor to
395 * schedule another I/O transfer.
743f1ef7 396 */
daaf7bee 397daddr_t
6d3d8a1c 398ffs_blkpref(ip, lbn, indx, bap)
4f083fd7
SL
399 struct inode *ip;
400 daddr_t lbn;
401 int indx;
402 daddr_t *bap;
f7287e4b 403{
4f083fd7 404 register struct fs *fs;
16e7863f
KM
405 register int cg;
406 int avgbfree, startcg;
4f083fd7 407 daddr_t nextblk;
743f1ef7 408
4f083fd7
SL
409 fs = ip->i_fs;
410 if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
411 if (lbn < NDADDR) {
412 cg = itog(fs, ip->i_number);
b6407c9d 413 return (fs->fs_fpg * cg + fs->fs_frag);
743f1ef7 414 }
4f083fd7
SL
415 /*
416 * Find a cylinder with greater than average number of
417 * unused data blocks.
418 */
16e7863f
KM
419 if (indx == 0 || bap[indx - 1] == 0)
420 startcg = itog(fs, ip->i_number) + lbn / fs->fs_maxbpg;
421 else
422 startcg = dtog(fs, bap[indx - 1]) + 1;
423 startcg %= fs->fs_ncg;
4f083fd7 424 avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
16e7863f 425 for (cg = startcg; cg < fs->fs_ncg; cg++)
4f083fd7
SL
426 if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
427 fs->fs_cgrotor = cg;
428 return (fs->fs_fpg * cg + fs->fs_frag);
429 }
16e7863f 430 for (cg = 0; cg <= startcg; cg++)
4f083fd7
SL
431 if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
432 fs->fs_cgrotor = cg;
433 return (fs->fs_fpg * cg + fs->fs_frag);
434 }
435 return (NULL);
436 }
437 /*
438 * One or more previous blocks have been laid out. If less
439 * than fs_maxcontig previous blocks are contiguous, the
440 * next block is requested contiguously, otherwise it is
441 * requested rotationally delayed by fs_rotdelay milliseconds.
442 */
443 nextblk = bap[indx - 1] + fs->fs_frag;
444 if (indx > fs->fs_maxcontig &&
240a4664 445 bap[indx - fs->fs_maxcontig] + blkstofrags(fs, fs->fs_maxcontig)
4f083fd7
SL
446 != nextblk)
447 return (nextblk);
448 if (fs->fs_rotdelay != 0)
449 /*
450 * Here we convert ms of delay to frags as:
451 * (frags) = (ms) * (rev/sec) * (sect/rev) /
452 * ((sect/frag) * (ms/sec))
453 * then round up to the next block.
454 */
455 nextblk += roundup(fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect /
456 (NSPF(fs) * 1000), fs->fs_frag);
457 return (nextblk);
743f1ef7
KM
458}
459
502770a3
KM
460/*
461 * Implement the cylinder overflow algorithm.
462 *
463 * The policy implemented by this algorithm is:
464 * 1) allocate the block in its requested cylinder group.
465 * 2) quadradically rehash on the cylinder group number.
466 * 3) brute force search for a free block.
467 */
daaf7bee 468/*VARARGS5*/
6d3d8a1c
KB
469static u_long
470ffs_hashalloc(ip, cg, pref, size, allocator)
f7287e4b 471 struct inode *ip;
e3fe2d69
KM
472 int cg;
473 long pref;
474 int size; /* size for data blocks, mode for inodes */
daaf7bee 475 u_long (*allocator)();
e3fe2d69 476{
f7287e4b 477 register struct fs *fs;
e3fe2d69
KM
478 long result;
479 int i, icg = cg;
480
f7287e4b 481 fs = ip->i_fs;
e3fe2d69
KM
482 /*
483 * 1: preferred cylinder group
484 */
f7287e4b 485 result = (*allocator)(ip, cg, pref, size);
e3fe2d69
KM
486 if (result)
487 return (result);
488 /*
489 * 2: quadratic rehash
490 */
491 for (i = 1; i < fs->fs_ncg; i *= 2) {
492 cg += i;
493 if (cg >= fs->fs_ncg)
494 cg -= fs->fs_ncg;
f7287e4b 495 result = (*allocator)(ip, cg, 0, size);
e3fe2d69
KM
496 if (result)
497 return (result);
498 }
499 /*
500 * 3: brute force search
620b3290
SL
501 * Note that we start at i == 2, since 0 was checked initially,
502 * and 1 is always checked in the quadratic rehash.
e3fe2d69 503 */
2136305e 504 cg = (icg + 2) % fs->fs_ncg;
620b3290 505 for (i = 2; i < fs->fs_ncg; i++) {
f7287e4b 506 result = (*allocator)(ip, cg, 0, size);
e3fe2d69
KM
507 if (result)
508 return (result);
509 cg++;
510 if (cg == fs->fs_ncg)
511 cg = 0;
512 }
ae851115 513 return (NULL);
e3fe2d69
KM
514}
515
502770a3
KM
516/*
517 * Determine whether a fragment can be extended.
518 *
519 * Check to see if the necessary fragments are available, and
520 * if they are, allocate them.
521 */
6d3d8a1c
KB
522static daddr_t
523ffs_fragextend(ip, cg, bprev, osize, nsize)
f7287e4b 524 struct inode *ip;
07670f7d 525 int cg;
f3c028b7 526 long bprev;
07670f7d
KM
527 int osize, nsize;
528{
f7287e4b 529 register struct fs *fs;
f3c028b7 530 register struct cg *cgp;
7188ac27 531 struct buf *bp;
f3c028b7
KM
532 long bno;
533 int frags, bbase;
7188ac27 534 int i, error;
07670f7d 535
f7287e4b 536 fs = ip->i_fs;
a8580723 537 if (fs->fs_cs(fs, cg).cs_nffree < numfrags(fs, nsize - osize))
e5476900 538 return (NULL);
d995d89d 539 frags = numfrags(fs, nsize);
a8580723
KM
540 bbase = fragnum(fs, bprev);
541 if (bbase > fragnum(fs, (bprev + frags - 1))) {
ec67a3ce 542 /* cannot extend across a block boundary */
ae851115 543 return (NULL);
f3c028b7 544 }
ec67a3ce
MK
545#ifdef SECSIZE
546 bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
547 fs->fs_dbsize);
548#else SECSIZE
7188ac27 549 error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
a937f856 550 (int)fs->fs_cgsize, NOCRED, &bp);
7188ac27
KM
551 if (error) {
552 brelse(bp);
553 return (NULL);
554 }
ec67a3ce 555#endif SECSIZE
e5476900 556 cgp = bp->b_un.b_cg;
7188ac27 557 if (!cg_chkmagic(cgp)) {
d995d89d 558 brelse(bp);
ae851115 559 return (NULL);
d995d89d 560 }
95d0807c 561 cgp->cg_time = time.tv_sec;
6994bf5d 562 bno = dtogd(fs, bprev);
d995d89d 563 for (i = numfrags(fs, osize); i < frags; i++)
10adeb11 564 if (isclr(cg_blksfree(cgp), bno + i)) {
aca50d72 565 brelse(bp);
ae851115 566 return (NULL);
aca50d72
KM
567 }
568 /*
569 * the current fragment can be extended
570 * deduct the count on fragment being extended into
571 * increase the count on the remaining fragment (if any)
572 * allocate the extended piece
573 */
574 for (i = frags; i < fs->fs_frag - bbase; i++)
10adeb11 575 if (isclr(cg_blksfree(cgp), bno + i))
f3c028b7 576 break;
d995d89d 577 cgp->cg_frsum[i - numfrags(fs, osize)]--;
aca50d72
KM
578 if (i != frags)
579 cgp->cg_frsum[i - frags]++;
d995d89d 580 for (i = numfrags(fs, osize); i < frags; i++) {
10adeb11 581 clrbit(cg_blksfree(cgp), bno + i);
aca50d72
KM
582 cgp->cg_cs.cs_nffree--;
583 fs->fs_cstotal.cs_nffree--;
584 fs->fs_cs(fs, cg).cs_nffree--;
f3c028b7 585 }
e809642a 586 fs->fs_fmod = 1;
aca50d72
KM
587 bdwrite(bp);
588 return (bprev);
07670f7d
KM
589}
590
502770a3
KM
591/*
592 * Determine whether a block can be allocated.
593 *
594 * Check to see if a block of the apprpriate size is available,
595 * and if it is, allocate it.
596 */
cd434177 597static daddr_t
6d3d8a1c 598ffs_alloccg(ip, cg, bpref, size)
f7287e4b 599 struct inode *ip;
e3fe2d69
KM
600 int cg;
601 daddr_t bpref;
602 int size;
603{
f7287e4b 604 register struct fs *fs;
f3c028b7 605 register struct cg *cgp;
7188ac27 606 struct buf *bp;
f3c028b7 607 register int i;
7188ac27 608 int error, bno, frags, allocsiz;
e3fe2d69 609
f7287e4b 610 fs = ip->i_fs;
b6407c9d 611 if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize)
ae851115 612 return (NULL);
ec67a3ce
MK
613#ifdef SECSIZE
614 bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
615 fs->fs_dbsize);
616#else SECSIZE
7188ac27 617 error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
a937f856 618 (int)fs->fs_cgsize, NOCRED, &bp);
7188ac27
KM
619 if (error) {
620 brelse(bp);
621 return (NULL);
622 }
ec67a3ce 623#endif SECSIZE
e5476900 624 cgp = bp->b_un.b_cg;
7188ac27 625 if (!cg_chkmagic(cgp) ||
0f538882 626 (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) {
d995d89d 627 brelse(bp);
ae851115 628 return (NULL);
d995d89d 629 }
95d0807c 630 cgp->cg_time = time.tv_sec;
b6407c9d 631 if (size == fs->fs_bsize) {
6d3d8a1c 632 bno = ffs_alloccgblk(fs, cgp, bpref);
f3c028b7
KM
633 bdwrite(bp);
634 return (bno);
635 }
636 /*
637 * check to see if any fragments are already available
638 * allocsiz is the size which will be allocated, hacking
639 * it down to a smaller size if necessary
640 */
d995d89d 641 frags = numfrags(fs, size);
b6407c9d 642 for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++)
f3c028b7
KM
643 if (cgp->cg_frsum[allocsiz] != 0)
644 break;
b6407c9d 645 if (allocsiz == fs->fs_frag) {
f3c028b7
KM
646 /*
647 * no fragments were available, so a block will be
648 * allocated, and hacked up
649 */
0947395d 650 if (cgp->cg_cs.cs_nbfree == 0) {
f3c028b7 651 brelse(bp);
ae851115 652 return (NULL);
f3c028b7 653 }
6d3d8a1c 654 bno = ffs_alloccgblk(fs, cgp, bpref);
6994bf5d 655 bpref = dtogd(fs, bno);
b6407c9d 656 for (i = frags; i < fs->fs_frag; i++)
10adeb11 657 setbit(cg_blksfree(cgp), bpref + i);
b6407c9d 658 i = fs->fs_frag - frags;
0947395d
KM
659 cgp->cg_cs.cs_nffree += i;
660 fs->fs_cstotal.cs_nffree += i;
b6407c9d 661 fs->fs_cs(fs, cg).cs_nffree += i;
e809642a 662 fs->fs_fmod = 1;
f3c028b7
KM
663 cgp->cg_frsum[i]++;
664 bdwrite(bp);
665 return (bno);
666 }
6d3d8a1c 667 bno = ffs_mapsearch(fs, cgp, bpref, allocsiz);
0f538882
KM
668 if (bno < 0) {
669 brelse(bp);
ae851115 670 return (NULL);
0f538882 671 }
f3c028b7 672 for (i = 0; i < frags; i++)
10adeb11 673 clrbit(cg_blksfree(cgp), bno + i);
0947395d
KM
674 cgp->cg_cs.cs_nffree -= frags;
675 fs->fs_cstotal.cs_nffree -= frags;
b6407c9d 676 fs->fs_cs(fs, cg).cs_nffree -= frags;
e809642a 677 fs->fs_fmod = 1;
f3c028b7
KM
678 cgp->cg_frsum[allocsiz]--;
679 if (frags != allocsiz)
680 cgp->cg_frsum[allocsiz - frags]++;
681 bdwrite(bp);
682 return (cg * fs->fs_fpg + bno);
683}
684
502770a3
KM
685/*
686 * Allocate a block in a cylinder group.
687 *
688 * This algorithm implements the following policy:
689 * 1) allocate the requested block.
690 * 2) allocate a rotationally optimal block in the same cylinder.
691 * 3) allocate the next available block on the block rotor for the
692 * specified cylinder group.
693 * Note that this routine only allocates fs_bsize blocks; these
694 * blocks may be fragmented by the routine that allocates them.
695 */
6d3d8a1c
KB
696static daddr_t
697ffs_alloccgblk(fs, cgp, bpref)
f7287e4b 698 register struct fs *fs;
f3c028b7
KM
699 register struct cg *cgp;
700 daddr_t bpref;
701{
743f1ef7 702 daddr_t bno;
ae851115 703 int cylno, pos, delta;
743f1ef7 704 short *cylbp;
aca50d72 705 register int i;
f3c028b7 706
743f1ef7
KM
707 if (bpref == 0) {
708 bpref = cgp->cg_rotor;
aca50d72
KM
709 goto norot;
710 }
a8580723 711 bpref = blknum(fs, bpref);
6994bf5d 712 bpref = dtogd(fs, bpref);
aca50d72
KM
713 /*
714 * if the requested block is available, use it
715 */
6d3d8a1c 716 if (ffs_isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bpref))) {
aca50d72
KM
717 bno = bpref;
718 goto gotit;
719 }
aca50d72
KM
720 /*
721 * check for a block available on the same cylinder
aca50d72
KM
722 */
723 cylno = cbtocylno(fs, bpref);
10adeb11 724 if (cg_blktot(cgp)[cylno] == 0)
502770a3
KM
725 goto norot;
726 if (fs->fs_cpc == 0) {
727 /*
728 * block layout info is not available, so just have
729 * to take any block in this cylinder.
730 */
731 bpref = howmany(fs->fs_spc * cylno, NSPF(fs));
732 goto norot;
733 }
aca50d72
KM
734 /*
735 * check the summary information to see if a block is
736 * available in the requested cylinder starting at the
4f083fd7 737 * requested rotational position and proceeding around.
aca50d72 738 */
10adeb11 739 cylbp = cg_blks(fs, cgp, cylno);
4f083fd7 740 pos = cbtorpos(fs, bpref);
10adeb11 741 for (i = pos; i < fs->fs_nrpos; i++)
aca50d72
KM
742 if (cylbp[i] > 0)
743 break;
10adeb11 744 if (i == fs->fs_nrpos)
aca50d72 745 for (i = 0; i < pos; i++)
743f1ef7
KM
746 if (cylbp[i] > 0)
747 break;
aca50d72
KM
748 if (cylbp[i] > 0) {
749 /*
750 * found a rotational position, now find the actual
751 * block. A panic if none is actually there.
752 */
753 pos = cylno % fs->fs_cpc;
754 bno = (cylno - pos) * fs->fs_spc / NSPB(fs);
10adeb11 755 if (fs_postbl(fs, pos)[i] == -1) {
ffd90e52
KM
756 printf("pos = %d, i = %d, fs = %s\n",
757 pos, i, fs->fs_fsmnt);
6d3d8a1c 758 panic("ffs_alloccgblk: cyl groups corrupted");
ffd90e52 759 }
10adeb11 760 for (i = fs_postbl(fs, pos)[i];; ) {
6d3d8a1c 761 if (ffs_isblock(fs, cg_blksfree(cgp), bno + i)) {
240a4664 762 bno = blkstofrags(fs, (bno + i));
aca50d72 763 goto gotit;
743f1ef7 764 }
10adeb11
KM
765 delta = fs_rotbl(fs)[i];
766 if (delta <= 0 ||
767 delta + i > fragstoblks(fs, fs->fs_fpg))
aca50d72 768 break;
ae851115 769 i += delta;
743f1ef7 770 }
ffd90e52 771 printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt);
6d3d8a1c 772 panic("ffs_alloccgblk: can't find blk in cyl");
e3fe2d69 773 }
aca50d72
KM
774norot:
775 /*
776 * no blocks in the requested cylinder, so take next
777 * available one in this cylinder group.
778 */
6d3d8a1c 779 bno = ffs_mapsearch(fs, cgp, bpref, (int)fs->fs_frag);
6459ebe0 780 if (bno < 0)
ae851115 781 return (NULL);
743f1ef7 782 cgp->cg_rotor = bno;
e3fe2d69 783gotit:
6d3d8a1c 784 ffs_clrblock(fs, cg_blksfree(cgp), (long)fragstoblks(fs, bno));
0947395d
KM
785 cgp->cg_cs.cs_nbfree--;
786 fs->fs_cstotal.cs_nbfree--;
b6407c9d 787 fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--;
502770a3 788 cylno = cbtocylno(fs, bno);
10adeb11
KM
789 cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--;
790 cg_blktot(cgp)[cylno]--;
e809642a 791 fs->fs_fmod = 1;
743f1ef7 792 return (cgp->cg_cgx * fs->fs_fpg + bno);
e3fe2d69 793}
10adeb11 794
502770a3
KM
795/*
796 * Determine whether an inode can be allocated.
797 *
798 * Check to see if an inode is available, and if it is,
799 * allocate it using the following policy:
800 * 1) allocate the requested inode.
801 * 2) allocate the next available inode after the requested
802 * inode in the specified cylinder group.
803 */
6d3d8a1c
KB
804static ino_t
805ffs_ialloccg(ip, cg, ipref, mode)
f7287e4b 806 struct inode *ip;
e3fe2d69
KM
807 int cg;
808 daddr_t ipref;
809 int mode;
810{
f7287e4b 811 register struct fs *fs;
f3c028b7 812 register struct cg *cgp;
4e0c7b8a 813 struct buf *bp;
7188ac27 814 int error, start, len, loc, map, i;
e3fe2d69 815
f7287e4b 816 fs = ip->i_fs;
b6407c9d 817 if (fs->fs_cs(fs, cg).cs_nifree == 0)
ae851115 818 return (NULL);
ec67a3ce
MK
819#ifdef SECSIZE
820 bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
821 fs->fs_dbsize);
822#else SECSIZE
7188ac27 823 error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
a937f856 824 (int)fs->fs_cgsize, NOCRED, &bp);
7188ac27
KM
825 if (error) {
826 brelse(bp);
827 return (NULL);
828 }
ec67a3ce 829#endif SECSIZE
e5476900 830 cgp = bp->b_un.b_cg;
7188ac27 831 if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) {
d995d89d 832 brelse(bp);
ae851115 833 return (NULL);
d995d89d 834 }
95d0807c 835 cgp->cg_time = time.tv_sec;
e3fe2d69
KM
836 if (ipref) {
837 ipref %= fs->fs_ipg;
10adeb11 838 if (isclr(cg_inosused(cgp), ipref))
e3fe2d69 839 goto gotit;
4e0c7b8a
KM
840 }
841 start = cgp->cg_irotor / NBBY;
842 len = howmany(fs->fs_ipg - cgp->cg_irotor, NBBY);
10adeb11 843 loc = skpc(0xff, len, &cg_inosused(cgp)[start]);
4e0c7b8a 844 if (loc == 0) {
e5889092
KM
845 len = start + 1;
846 start = 0;
10adeb11 847 loc = skpc(0xff, len, &cg_inosused(cgp)[0]);
e5889092
KM
848 if (loc == 0) {
849 printf("cg = %s, irotor = %d, fs = %s\n",
850 cg, cgp->cg_irotor, fs->fs_fsmnt);
6d3d8a1c 851 panic("ffs_ialloccg: map corrupted");
e5889092
KM
852 /* NOTREACHED */
853 }
4e0c7b8a
KM
854 }
855 i = start + len - loc;
10adeb11 856 map = cg_inosused(cgp)[i];
4e0c7b8a
KM
857 ipref = i * NBBY;
858 for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) {
859 if ((map & i) == 0) {
e3fe2d69
KM
860 cgp->cg_irotor = ipref;
861 goto gotit;
862 }
863 }
4e0c7b8a 864 printf("fs = %s\n", fs->fs_fsmnt);
6d3d8a1c 865 panic("ffs_ialloccg: block not in map");
4e0c7b8a 866 /* NOTREACHED */
e3fe2d69 867gotit:
10adeb11 868 setbit(cg_inosused(cgp), ipref);
0947395d
KM
869 cgp->cg_cs.cs_nifree--;
870 fs->fs_cstotal.cs_nifree--;
b6407c9d 871 fs->fs_cs(fs, cg).cs_nifree--;
e809642a 872 fs->fs_fmod = 1;
e3fe2d69 873 if ((mode & IFMT) == IFDIR) {
0947395d
KM
874 cgp->cg_cs.cs_ndir++;
875 fs->fs_cstotal.cs_ndir++;
b6407c9d 876 fs->fs_cs(fs, cg).cs_ndir++;
e3fe2d69
KM
877 }
878 bdwrite(bp);
879 return (cg * fs->fs_ipg + ipref);
880}
881
502770a3
KM
882/*
883 * Free a block or fragment.
884 *
885 * The specified block or fragment is placed back in the
886 * free map. If a fragment is deallocated, a possible
887 * block reassembly is checked.
888 */
6d3d8a1c 889ffs_blkfree(ip, bno, size)
f7287e4b 890 register struct inode *ip;
e3fe2d69 891 daddr_t bno;
31cd85c7 892 long size;
e3fe2d69
KM
893{
894 register struct fs *fs;
895 register struct cg *cgp;
7188ac27
KM
896 struct buf *bp;
897 int error, cg, blk, frags, bbase;
f3c028b7 898 register int i;
e3fe2d69 899
f7287e4b 900 fs = ip->i_fs;
ffd90e52
KM
901 if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) {
902 printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n",
903 ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt);
ced3a252 904 panic("blkfree: bad size");
ffd90e52 905 }
6994bf5d 906 cg = dtog(fs, bno);
e2546752 907 if ((unsigned)bno >= fs->fs_size) {
6459ebe0 908 printf("bad block %d, ino %d\n", bno, ip->i_number);
9438887a 909 ffs_fserr(fs, ip->i_uid, "bad block");
e3fe2d69 910 return;
6459ebe0 911 }
ec67a3ce
MK
912#ifdef SECSIZE
913 bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
914 fs->fs_dbsize);
915#else SECSIZE
7188ac27 916 error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
a937f856 917 (int)fs->fs_cgsize, NOCRED, &bp);
7188ac27
KM
918 if (error) {
919 brelse(bp);
920 return;
921 }
ec67a3ce 922#endif SECSIZE
e5476900 923 cgp = bp->b_un.b_cg;
7188ac27 924 if (!cg_chkmagic(cgp)) {
d995d89d 925 brelse(bp);
e3fe2d69 926 return;
d995d89d 927 }
95d0807c 928 cgp->cg_time = time.tv_sec;
6994bf5d 929 bno = dtogd(fs, bno);
b6407c9d 930 if (size == fs->fs_bsize) {
6d3d8a1c 931 if (ffs_isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bno))) {
ffd90e52
KM
932 printf("dev = 0x%x, block = %d, fs = %s\n",
933 ip->i_dev, bno, fs->fs_fsmnt);
ced3a252 934 panic("blkfree: freeing free block");
6459ebe0 935 }
6d3d8a1c 936 ffs_setblock(fs, cg_blksfree(cgp), fragstoblks(fs, bno));
0947395d
KM
937 cgp->cg_cs.cs_nbfree++;
938 fs->fs_cstotal.cs_nbfree++;
b6407c9d 939 fs->fs_cs(fs, cg).cs_nbfree++;
502770a3 940 i = cbtocylno(fs, bno);
10adeb11
KM
941 cg_blks(fs, cgp, i)[cbtorpos(fs, bno)]++;
942 cg_blktot(cgp)[i]++;
07670f7d 943 } else {
a8580723 944 bbase = bno - fragnum(fs, bno);
f3c028b7
KM
945 /*
946 * decrement the counts associated with the old frags
947 */
10adeb11 948 blk = blkmap(fs, cg_blksfree(cgp), bbase);
6d3d8a1c 949 ffs_fragacct(fs, blk, cgp->cg_frsum, -1);
f3c028b7
KM
950 /*
951 * deallocate the fragment
952 */
d995d89d 953 frags = numfrags(fs, size);
f3c028b7 954 for (i = 0; i < frags; i++) {
10adeb11 955 if (isset(cg_blksfree(cgp), bno + i)) {
ffd90e52
KM
956 printf("dev = 0x%x, block = %d, fs = %s\n",
957 ip->i_dev, bno + i, fs->fs_fsmnt);
ced3a252 958 panic("blkfree: freeing free frag");
ffd90e52 959 }
10adeb11 960 setbit(cg_blksfree(cgp), bno + i);
07670f7d 961 }
ae851115
KM
962 cgp->cg_cs.cs_nffree += i;
963 fs->fs_cstotal.cs_nffree += i;
964 fs->fs_cs(fs, cg).cs_nffree += i;
f3c028b7
KM
965 /*
966 * add back in counts associated with the new frags
967 */
10adeb11 968 blk = blkmap(fs, cg_blksfree(cgp), bbase);
6d3d8a1c 969 ffs_fragacct(fs, blk, cgp->cg_frsum, 1);
f3c028b7
KM
970 /*
971 * if a complete block has been reassembled, account for it
972 */
6d3d8a1c 973 if (ffs_isblock(fs, cg_blksfree(cgp),
9523729e 974 (daddr_t)fragstoblks(fs, bbase))) {
b6407c9d
KM
975 cgp->cg_cs.cs_nffree -= fs->fs_frag;
976 fs->fs_cstotal.cs_nffree -= fs->fs_frag;
977 fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag;
0947395d
KM
978 cgp->cg_cs.cs_nbfree++;
979 fs->fs_cstotal.cs_nbfree++;
b6407c9d 980 fs->fs_cs(fs, cg).cs_nbfree++;
502770a3 981 i = cbtocylno(fs, bbase);
10adeb11
KM
982 cg_blks(fs, cgp, i)[cbtorpos(fs, bbase)]++;
983 cg_blktot(cgp)[i]++;
07670f7d
KM
984 }
985 }
e809642a 986 fs->fs_fmod = 1;
e3fe2d69
KM
987 bdwrite(bp);
988}
989
502770a3
KM
990/*
991 * Free an inode.
992 *
993 * The specified inode is placed back in the free map.
994 */
6d3d8a1c 995void
a9013e03
KM
996ffs_vfree(pvp, ino, mode)
997 struct vnode *pvp;
e3fe2d69
KM
998 ino_t ino;
999 int mode;
1000{
1001 register struct fs *fs;
1002 register struct cg *cgp;
a9013e03 1003 register struct inode *pip;
7188ac27
KM
1004 struct buf *bp;
1005 int error, cg;
e3fe2d69 1006
a9013e03 1007 pip = VTOI(pvp);
6d3d8a1c
KB
1008 fs = pip->i_fs;
1009 if ((u_int)ino >= fs->fs_ipg * fs->fs_ncg)
1010 panic("ifree: range: dev = 0x%x, ino = %d, fs = %s\n",
1011 pip->i_dev, ino, fs->fs_fsmnt);
6994bf5d 1012 cg = itog(fs, ino);
ec67a3ce
MK
1013#ifdef SECSIZE
1014 bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
1015 fs->fs_dbsize);
1016#else SECSIZE
6d3d8a1c 1017 error = bread(pip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
a937f856 1018 (int)fs->fs_cgsize, NOCRED, &bp);
7188ac27
KM
1019 if (error) {
1020 brelse(bp);
1021 return;
1022 }
ec67a3ce 1023#endif SECSIZE
e5476900 1024 cgp = bp->b_un.b_cg;
7188ac27 1025 if (!cg_chkmagic(cgp)) {
d995d89d 1026 brelse(bp);
e3fe2d69 1027 return;
d995d89d 1028 }
95d0807c 1029 cgp->cg_time = time.tv_sec;
e3fe2d69 1030 ino %= fs->fs_ipg;
10adeb11 1031 if (isclr(cg_inosused(cgp), ino)) {
ffd90e52 1032 printf("dev = 0x%x, ino = %d, fs = %s\n",
6d3d8a1c 1033 pip->i_dev, ino, fs->fs_fsmnt);
b9ccf514
KM
1034 if (fs->fs_ronly == 0)
1035 panic("ifree: freeing free inode");
ffd90e52 1036 }
10adeb11 1037 clrbit(cg_inosused(cgp), ino);
4e0c7b8a
KM
1038 if (ino < cgp->cg_irotor)
1039 cgp->cg_irotor = ino;
0947395d
KM
1040 cgp->cg_cs.cs_nifree++;
1041 fs->fs_cstotal.cs_nifree++;
b6407c9d 1042 fs->fs_cs(fs, cg).cs_nifree++;
e3fe2d69 1043 if ((mode & IFMT) == IFDIR) {
0947395d
KM
1044 cgp->cg_cs.cs_ndir--;
1045 fs->fs_cstotal.cs_ndir--;
b6407c9d 1046 fs->fs_cs(fs, cg).cs_ndir--;
e3fe2d69 1047 }
e809642a 1048 fs->fs_fmod = 1;
e3fe2d69
KM
1049 bdwrite(bp);
1050}
1051
743f1ef7 1052/*
502770a3
KM
1053 * Find a block of the specified size in the specified cylinder group.
1054 *
743f1ef7
KM
1055 * It is a panic if a request is made to find a block if none are
1056 * available.
1057 */
6d3d8a1c
KB
1058static daddr_t
1059ffs_mapsearch(fs, cgp, bpref, allocsiz)
743f1ef7
KM
1060 register struct fs *fs;
1061 register struct cg *cgp;
1062 daddr_t bpref;
1063 int allocsiz;
1064{
1065 daddr_t bno;
1066 int start, len, loc, i;
1067 int blk, field, subfield, pos;
1068
1069 /*
1070 * find the fragment by searching through the free block
1071 * map for an appropriate bit pattern
1072 */
1073 if (bpref)
6994bf5d 1074 start = dtogd(fs, bpref) / NBBY;
743f1ef7
KM
1075 else
1076 start = cgp->cg_frotor / NBBY;
942bd18b 1077 len = howmany(fs->fs_fpg, NBBY) - start;
9523729e
KM
1078 loc = scanc((unsigned)len, (u_char *)&cg_blksfree(cgp)[start],
1079 (u_char *)fragtbl[fs->fs_frag],
1080 (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));
743f1ef7 1081 if (loc == 0) {
e5476900
KM
1082 len = start + 1;
1083 start = 0;
9523729e
KM
1084 loc = scanc((unsigned)len, (u_char *)&cg_blksfree(cgp)[0],
1085 (u_char *)fragtbl[fs->fs_frag],
1086 (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));
4e0c7b8a
KM
1087 if (loc == 0) {
1088 printf("start = %d, len = %d, fs = %s\n",
1089 start, len, fs->fs_fsmnt);
6d3d8a1c 1090 panic("ffs_alloccg: map corrupted");
e5889092 1091 /* NOTREACHED */
4e0c7b8a 1092 }
743f1ef7
KM
1093 }
1094 bno = (start + len - loc) * NBBY;
1095 cgp->cg_frotor = bno;
1096 /*
1097 * found the byte in the map
1098 * sift through the bits to find the selected frag
1099 */
ae851115 1100 for (i = bno + NBBY; bno < i; bno += fs->fs_frag) {
10adeb11 1101 blk = blkmap(fs, cg_blksfree(cgp), bno);
743f1ef7
KM
1102 blk <<= 1;
1103 field = around[allocsiz];
1104 subfield = inside[allocsiz];
b6407c9d 1105 for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) {
ae851115
KM
1106 if ((blk & field) == subfield)
1107 return (bno + pos);
743f1ef7
KM
1108 field <<= 1;
1109 subfield <<= 1;
1110 }
1111 }
ffd90e52 1112 printf("bno = %d, fs = %s\n", bno, fs->fs_fsmnt);
6d3d8a1c 1113 panic("ffs_alloccg: block not in map");
e5476900 1114 return (-1);
743f1ef7
KM
1115}
1116
e3fe2d69 1117/*
502770a3
KM
1118 * Fserr prints the name of a file system with an error diagnostic.
1119 *
1120 * The form of the error message is:
e3fe2d69
KM
1121 * fs: error message
1122 */
6d3d8a1c
KB
1123static void
1124ffs_fserr(fs, uid, cp)
e3fe2d69 1125 struct fs *fs;
6d3d8a1c 1126 u_int uid;
e3fe2d69
KM
1127 char *cp;
1128{
1129
e2546752 1130 log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp);
e3fe2d69 1131}