1 /* $NetBSD: ext2fs_alloc.c,v 1.38 2009/01/11 02:45:56 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)ffs_alloc.c 8.11 (Berkeley) 10/27/94 32 * Modified for ext2fs by Manuel Bouyer. 33 */ 34 35 /* 36 * Copyright (c) 1997 Manuel Bouyer. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed by Manuel Bouyer. 49 * 4. The name of the author may not be used to endorse or promote products 50 * derived from this software without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 53 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 54 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 55 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 56 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 57 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 61 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 * 63 * @(#)ffs_alloc.c 8.11 (Berkeley) 10/27/94 64 * Modified for ext2fs by Manuel Bouyer. 65 */ 66 67 #include <sys/cdefs.h> 68 __KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.38 2009/01/11 02:45:56 christos Exp $"); 69 70 #include <sys/param.h> 71 #include <sys/systm.h> 72 #include <sys/buf.h> 73 #include <sys/proc.h> 74 #include <sys/vnode.h> 75 #include <sys/mount.h> 76 #include <sys/kernel.h> 77 #include <sys/syslog.h> 78 #include <sys/kauth.h> 79 80 #include <ufs/ufs/inode.h> 81 #include <ufs/ufs/ufs_extern.h> 82 #include <ufs/ufs/ufsmount.h> 83 84 #include <ufs/ext2fs/ext2fs.h> 85 #include <ufs/ext2fs/ext2fs_extern.h> 86 87 u_long ext2gennumber; 88 89 static daddr_t ext2fs_alloccg(struct inode *, int, daddr_t, int); 90 static u_long ext2fs_dirpref(struct m_ext2fs *); 91 static void ext2fs_fserr(struct m_ext2fs *, u_int, const char *); 92 static u_long ext2fs_hashalloc(struct inode *, int, long, int, 93 daddr_t (*)(struct inode *, int, daddr_t, 94 int)); 95 static daddr_t ext2fs_nodealloccg(struct inode *, int, daddr_t, int); 96 static daddr_t ext2fs_mapsearch(struct m_ext2fs *, char *, daddr_t); 97 98 /* 99 * Allocate a block in the file system. 100 * 101 * A preference may be optionally specified. If a preference is given 102 * the following hierarchy is used to allocate a block: 103 * 1) allocate the requested block. 104 * 2) allocate a rotationally optimal block in the same cylinder. 105 * 3) allocate a block in the same cylinder group. 106 * 4) quadradically rehash into other cylinder groups, until an 107 * available block is located. 108 * If no block preference is given the following hierarchy is used 109 * to allocate a block: 110 * 1) allocate a block in the cylinder group that contains the 111 * inode for the file. 112 * 2) quadradically rehash into other cylinder groups, until an 113 * available block is located. 114 */ 115 int 116 ext2fs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, 117 kauth_cred_t cred, daddr_t *bnp) 118 { 119 struct m_ext2fs *fs; 120 daddr_t bno; 121 int cg; 122 123 *bnp = 0; 124 fs = ip->i_e2fs; 125 #ifdef DIAGNOSTIC 126 if (cred == NOCRED) 127 panic("ext2fs_alloc: missing credential"); 128 #endif /* DIAGNOSTIC */ 129 if (fs->e2fs.e2fs_fbcount == 0) 130 goto nospace; 131 if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) != 0 && 132 freespace(fs) <= 0) 133 goto nospace; 134 if (bpref >= fs->e2fs.e2fs_bcount) 135 bpref = 0; 136 if (bpref == 0) 137 cg = ino_to_cg(fs, ip->i_number); 138 else 139 cg = dtog(fs, bpref); 140 bno = (daddr_t)ext2fs_hashalloc(ip, cg, bpref, fs->e2fs_bsize, 141 ext2fs_alloccg); 142 if (bno > 0) { 143 ip->i_e2fs_nblock += btodb(fs->e2fs_bsize); 144 ip->i_flag |= IN_CHANGE | IN_UPDATE; 145 *bnp = bno; 146 return (0); 147 } 148 nospace: 149 ext2fs_fserr(fs, kauth_cred_geteuid(cred), "file system full"); 150 uprintf("\n%s: write failed, file system is full\n", fs->e2fs_fsmnt); 151 return (ENOSPC); 152 } 153 154 /* 155 * Allocate an inode in the file system. 156 * 157 * If allocating a directory, use ext2fs_dirpref to select the inode. 158 * If allocating in a directory, the following hierarchy is followed: 159 * 1) allocate the preferred inode. 160 * 2) allocate an inode in the same cylinder group. 161 * 3) quadradically rehash into other cylinder groups, until an 162 * available inode is located. 163 * If no inode preference is given the following hierarchy is used 164 * to allocate an inode: 165 * 1) allocate an inode in cylinder group 0. 166 * 2) quadradically rehash into other cylinder groups, until an 167 * available inode is located. 168 */ 169 int 170 ext2fs_valloc(struct vnode *pvp, int mode, kauth_cred_t cred, 171 struct vnode **vpp) 172 { 173 struct inode *pip; 174 struct m_ext2fs *fs; 175 struct inode *ip; 176 ino_t ino, ipref; 177 int cg, error; 178 179 *vpp = NULL; 180 pip = VTOI(pvp); 181 fs = pip->i_e2fs; 182 if (fs->e2fs.e2fs_ficount == 0) 183 goto noinodes; 184 185 if ((mode & IFMT) == IFDIR) 186 cg = ext2fs_dirpref(fs); 187 else 188 cg = ino_to_cg(fs, pip->i_number); 189 ipref = cg * fs->e2fs.e2fs_ipg + 1; 190 ino = (ino_t)ext2fs_hashalloc(pip, cg, (long)ipref, mode, ext2fs_nodealloccg); 191 if (ino == 0) 192 goto noinodes; 193 error = VFS_VGET(pvp->v_mount, ino, vpp); 194 if (error) { 195 ext2fs_vfree(pvp, ino, mode); 196 return (error); 197 } 198 ip = VTOI(*vpp); 199 if (ip->i_e2fs_mode && ip->i_e2fs_nlink != 0) { 200 printf("mode = 0%o, nlinks %d, inum = %llu, fs = %s\n", 201 ip->i_e2fs_mode, ip->i_e2fs_nlink, 202 (unsigned long long)ip->i_number, fs->e2fs_fsmnt); 203 panic("ext2fs_valloc: dup alloc"); 204 } 205 206 memset(ip->i_din.e2fs_din, 0, sizeof(struct ext2fs_dinode)); 207 208 /* 209 * Set up a new generation number for this inode. 210 */ 211 if (++ext2gennumber < time_second) 212 ext2gennumber = time_second; 213 ip->i_e2fs_gen = ext2gennumber; 214 return (0); 215 noinodes: 216 ext2fs_fserr(fs, kauth_cred_geteuid(cred), "out of inodes"); 217 uprintf("\n%s: create/symlink failed, no inodes free\n", fs->e2fs_fsmnt); 218 return (ENOSPC); 219 } 220 221 /* 222 * Find a cylinder to place a directory. 223 * 224 * The policy implemented by this algorithm is to select from 225 * among those cylinder groups with above the average number of 226 * free inodes, the one with the smallest number of directories. 227 */ 228 static u_long 229 ext2fs_dirpref(struct m_ext2fs *fs) 230 { 231 int cg, maxspace, mincg, avgifree; 232 233 avgifree = fs->e2fs.e2fs_ficount / fs->e2fs_ncg; 234 maxspace = 0; 235 mincg = -1; 236 for (cg = 0; cg < fs->e2fs_ncg; cg++) 237 if ( fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree) { 238 if (mincg == -1 || fs->e2fs_gd[cg].ext2bgd_nbfree > maxspace) { 239 mincg = cg; 240 maxspace = fs->e2fs_gd[cg].ext2bgd_nbfree; 241 } 242 } 243 return mincg; 244 } 245 246 /* 247 * Select the desired position for the next block in a file. The file is 248 * logically divided into sections. The first section is composed of the 249 * direct blocks. Each additional section contains fs_maxbpg blocks. 250 * 251 * If no blocks have been allocated in the first section, the policy is to 252 * request a block in the same cylinder group as the inode that describes 253 * the file. Otherwise, the policy is to try to allocate the blocks 254 * contigously. The two fields of the ext2 inode extension (see 255 * ufs/ufs/inode.h) help this. 256 */ 257 daddr_t 258 ext2fs_blkpref(struct inode *ip, daddr_t lbn, int indx, 259 int32_t *bap /* XXX ondisk32 */) 260 { 261 struct m_ext2fs *fs; 262 int cg, i; 263 264 fs = ip->i_e2fs; 265 /* 266 * if we are doing contigous lbn allocation, try to alloc blocks 267 * contigously on disk 268 */ 269 270 if ( ip->i_e2fs_last_blk && lbn == ip->i_e2fs_last_lblk + 1) { 271 return ip->i_e2fs_last_blk + 1; 272 } 273 274 /* 275 * bap, if provided, gives us a list of blocks to which we want to 276 * stay close 277 */ 278 279 if (bap) { 280 for (i = indx; i >= 0 ; i--) { 281 if (bap[i]) { 282 return fs2h32(bap[i]) + 1; 283 } 284 } 285 } 286 287 /* fall back to the first block of the cylinder containing the inode */ 288 289 cg = ino_to_cg(fs, ip->i_number); 290 return fs->e2fs.e2fs_bpg * cg + fs->e2fs.e2fs_first_dblock + 1; 291 } 292 293 /* 294 * Implement the cylinder overflow algorithm. 295 * 296 * The policy implemented by this algorithm is: 297 * 1) allocate the block in its requested cylinder group. 298 * 2) quadradically rehash on the cylinder group number. 299 * 3) brute force search for a free block. 300 */ 301 static u_long 302 ext2fs_hashalloc(struct inode *ip, int cg, long pref, int size, 303 daddr_t (*allocator)(struct inode *, int, daddr_t, int)) 304 { 305 struct m_ext2fs *fs; 306 long result; 307 int i, icg = cg; 308 309 fs = ip->i_e2fs; 310 /* 311 * 1: preferred cylinder group 312 */ 313 result = (*allocator)(ip, cg, pref, size); 314 if (result) 315 return (result); 316 /* 317 * 2: quadratic rehash 318 */ 319 for (i = 1; i < fs->e2fs_ncg; i *= 2) { 320 cg += i; 321 if (cg >= fs->e2fs_ncg) 322 cg -= fs->e2fs_ncg; 323 result = (*allocator)(ip, cg, 0, size); 324 if (result) 325 return (result); 326 } 327 /* 328 * 3: brute force search 329 * Note that we start at i == 2, since 0 was checked initially, 330 * and 1 is always checked in the quadratic rehash. 331 */ 332 cg = (icg + 2) % fs->e2fs_ncg; 333 for (i = 2; i < fs->e2fs_ncg; i++) { 334 result = (*allocator)(ip, cg, 0, size); 335 if (result) 336 return (result); 337 cg++; 338 if (cg == fs->e2fs_ncg) 339 cg = 0; 340 } 341 return (0); 342 } 343 344 /* 345 * Determine whether a block can be allocated. 346 * 347 * Check to see if a block of the appropriate size is available, 348 * and if it is, allocate it. 349 */ 350 351 static daddr_t 352 ext2fs_alloccg(struct inode *ip, int cg, daddr_t bpref, int size) 353 { 354 struct m_ext2fs *fs; 355 char *bbp; 356 struct buf *bp; 357 /* XXX ondisk32 */ 358 int error, bno, start, end, loc; 359 360 fs = ip->i_e2fs; 361 if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0) 362 return (0); 363 error = bread(ip->i_devvp, fsbtodb(fs, 364 fs->e2fs_gd[cg].ext2bgd_b_bitmap), 365 (int)fs->e2fs_bsize, NOCRED, B_MODIFY, &bp); 366 if (error) { 367 brelse(bp, 0); 368 return (0); 369 } 370 bbp = (char *)bp->b_data; 371 372 if (dtog(fs, bpref) != cg) 373 bpref = 0; 374 if (bpref != 0) { 375 bpref = dtogd(fs, bpref); 376 /* 377 * if the requested block is available, use it 378 */ 379 if (isclr(bbp, bpref)) { 380 bno = bpref; 381 goto gotit; 382 } 383 } 384 /* 385 * no blocks in the requested cylinder, so take next 386 * available one in this cylinder group. 387 * first try to get 8 contigous blocks, then fall back to a single 388 * block. 389 */ 390 if (bpref) 391 start = dtogd(fs, bpref) / NBBY; 392 else 393 start = 0; 394 end = howmany(fs->e2fs.e2fs_fpg, NBBY) - start; 395 for (loc = start; loc < end; loc++) { 396 if (bbp[loc] == 0) { 397 bno = loc * NBBY; 398 goto gotit; 399 } 400 } 401 for (loc = 0; loc < start; loc++) { 402 if (bbp[loc] == 0) { 403 bno = loc * NBBY; 404 goto gotit; 405 } 406 } 407 408 bno = ext2fs_mapsearch(fs, bbp, bpref); 409 if (bno < 0) 410 return (0); 411 gotit: 412 #ifdef DIAGNOSTIC 413 if (isset(bbp, (daddr_t)bno)) { 414 printf("ext2fs_alloccgblk: cg=%d bno=%d fs=%s\n", 415 cg, bno, fs->e2fs_fsmnt); 416 panic("ext2fs_alloccg: dup alloc"); 417 } 418 #endif 419 setbit(bbp, (daddr_t)bno); 420 fs->e2fs.e2fs_fbcount--; 421 fs->e2fs_gd[cg].ext2bgd_nbfree--; 422 fs->e2fs_fmod = 1; 423 bdwrite(bp); 424 return (cg * fs->e2fs.e2fs_fpg + fs->e2fs.e2fs_first_dblock + bno); 425 } 426 427 /* 428 * Determine whether an inode can be allocated. 429 * 430 * Check to see if an inode is available, and if it is, 431 * allocate it using the following policy: 432 * 1) allocate the requested inode. 433 * 2) allocate the next available inode after the requested 434 * inode in the specified cylinder group. 435 */ 436 static daddr_t 437 ext2fs_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode) 438 { 439 struct m_ext2fs *fs; 440 char *ibp; 441 struct buf *bp; 442 int error, start, len, loc, map, i; 443 444 ipref--; /* to avoid a lot of (ipref -1) */ 445 if (ipref == -1) 446 ipref = 0; 447 fs = ip->i_e2fs; 448 if (fs->e2fs_gd[cg].ext2bgd_nifree == 0) 449 return (0); 450 error = bread(ip->i_devvp, fsbtodb(fs, 451 fs->e2fs_gd[cg].ext2bgd_i_bitmap), 452 (int)fs->e2fs_bsize, NOCRED, B_MODIFY, &bp); 453 if (error) { 454 brelse(bp, 0); 455 return (0); 456 } 457 ibp = (char *)bp->b_data; 458 if (ipref) { 459 ipref %= fs->e2fs.e2fs_ipg; 460 if (isclr(ibp, ipref)) 461 goto gotit; 462 } 463 start = ipref / NBBY; 464 len = howmany(fs->e2fs.e2fs_ipg - ipref, NBBY); 465 loc = skpc(0xff, len, &ibp[start]); 466 if (loc == 0) { 467 len = start + 1; 468 start = 0; 469 loc = skpc(0xff, len, &ibp[0]); 470 if (loc == 0) { 471 printf("cg = %d, ipref = %lld, fs = %s\n", 472 cg, (long long)ipref, fs->e2fs_fsmnt); 473 panic("ext2fs_nodealloccg: map corrupted"); 474 /* NOTREACHED */ 475 } 476 } 477 i = start + len - loc; 478 map = ibp[i]; 479 ipref = i * NBBY; 480 for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) { 481 if ((map & i) == 0) { 482 goto gotit; 483 } 484 } 485 printf("fs = %s\n", fs->e2fs_fsmnt); 486 panic("ext2fs_nodealloccg: block not in map"); 487 /* NOTREACHED */ 488 gotit: 489 setbit(ibp, ipref); 490 fs->e2fs.e2fs_ficount--; 491 fs->e2fs_gd[cg].ext2bgd_nifree--; 492 fs->e2fs_fmod = 1; 493 if ((mode & IFMT) == IFDIR) { 494 fs->e2fs_gd[cg].ext2bgd_ndirs++; 495 } 496 bdwrite(bp); 497 return (cg * fs->e2fs.e2fs_ipg + ipref +1); 498 } 499 500 /* 501 * Free a block. 502 * 503 * The specified block is placed back in the 504 * free map. 505 */ 506 void 507 ext2fs_blkfree(struct inode *ip, daddr_t bno) 508 { 509 struct m_ext2fs *fs; 510 char *bbp; 511 struct buf *bp; 512 int error, cg; 513 514 fs = ip->i_e2fs; 515 cg = dtog(fs, bno); 516 if ((u_int)bno >= fs->e2fs.e2fs_bcount) { 517 printf("bad block %lld, ino %llu\n", (long long)bno, 518 (unsigned long long)ip->i_number); 519 ext2fs_fserr(fs, ip->i_uid, "bad block"); 520 return; 521 } 522 error = bread(ip->i_devvp, 523 fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap), 524 (int)fs->e2fs_bsize, NOCRED, B_MODIFY, &bp); 525 if (error) { 526 brelse(bp, 0); 527 return; 528 } 529 bbp = (char *)bp->b_data; 530 bno = dtogd(fs, bno); 531 if (isclr(bbp, bno)) { 532 printf("dev = 0x%llx, block = %lld, fs = %s\n", 533 (unsigned long long)ip->i_dev, (long long)bno, 534 fs->e2fs_fsmnt); 535 panic("blkfree: freeing free block"); 536 } 537 clrbit(bbp, bno); 538 fs->e2fs.e2fs_fbcount++; 539 fs->e2fs_gd[cg].ext2bgd_nbfree++; 540 541 fs->e2fs_fmod = 1; 542 bdwrite(bp); 543 } 544 545 /* 546 * Free an inode. 547 * 548 * The specified inode is placed back in the free map. 549 */ 550 int 551 ext2fs_vfree(struct vnode *pvp, ino_t ino, int mode) 552 { 553 struct m_ext2fs *fs; 554 char *ibp; 555 struct inode *pip; 556 struct buf *bp; 557 int error, cg; 558 559 pip = VTOI(pvp); 560 fs = pip->i_e2fs; 561 if ((u_int)ino > fs->e2fs.e2fs_icount || (u_int)ino < EXT2_FIRSTINO) 562 panic("ifree: range: dev = 0x%llx, ino = %llu, fs = %s", 563 (unsigned long long)pip->i_dev, (unsigned long long)ino, 564 fs->e2fs_fsmnt); 565 cg = ino_to_cg(fs, ino); 566 error = bread(pip->i_devvp, 567 fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap), 568 (int)fs->e2fs_bsize, NOCRED, B_MODIFY, &bp); 569 if (error) { 570 brelse(bp, 0); 571 return (0); 572 } 573 ibp = (char *)bp->b_data; 574 ino = (ino - 1) % fs->e2fs.e2fs_ipg; 575 if (isclr(ibp, ino)) { 576 printf("dev = 0x%llx, ino = %llu, fs = %s\n", 577 (unsigned long long)pip->i_dev, 578 (unsigned long long)ino, fs->e2fs_fsmnt); 579 if (fs->e2fs_ronly == 0) 580 panic("ifree: freeing free inode"); 581 } 582 clrbit(ibp, ino); 583 fs->e2fs.e2fs_ficount++; 584 fs->e2fs_gd[cg].ext2bgd_nifree++; 585 if ((mode & IFMT) == IFDIR) { 586 fs->e2fs_gd[cg].ext2bgd_ndirs--; 587 } 588 fs->e2fs_fmod = 1; 589 bdwrite(bp); 590 return (0); 591 } 592 593 /* 594 * Find a block in the specified cylinder group. 595 * 596 * It is a panic if a request is made to find a block if none are 597 * available. 598 */ 599 600 static daddr_t 601 ext2fs_mapsearch(struct m_ext2fs *fs, char *bbp, daddr_t bpref) 602 { 603 daddr_t bno; 604 int start, len, loc, i, map; 605 606 /* 607 * find the fragment by searching through the free block 608 * map for an appropriate bit pattern 609 */ 610 if (bpref) 611 start = dtogd(fs, bpref) / NBBY; 612 else 613 start = 0; 614 len = howmany(fs->e2fs.e2fs_fpg, NBBY) - start; 615 loc = skpc(0xff, len, &bbp[start]); 616 if (loc == 0) { 617 len = start + 1; 618 start = 0; 619 loc = skpc(0xff, len, &bbp[start]); 620 if (loc == 0) { 621 printf("start = %d, len = %d, fs = %s\n", 622 start, len, fs->e2fs_fsmnt); 623 panic("ext2fs_alloccg: map corrupted"); 624 /* NOTREACHED */ 625 } 626 } 627 i = start + len - loc; 628 map = bbp[i]; 629 bno = i * NBBY; 630 for (i = 1; i < (1 << NBBY); i <<= 1, bno++) { 631 if ((map & i) == 0) 632 return (bno); 633 } 634 printf("fs = %s\n", fs->e2fs_fsmnt); 635 panic("ext2fs_mapsearch: block not in map"); 636 /* NOTREACHED */ 637 } 638 639 /* 640 * Fserr prints the name of a file system with an error diagnostic. 641 * 642 * The form of the error message is: 643 * fs: error message 644 */ 645 static void 646 ext2fs_fserr(struct m_ext2fs *fs, u_int uid, const char *cp) 647 { 648 649 log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->e2fs_fsmnt, cp); 650 } 651