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