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