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