1 /* $NetBSD: ext2fs_alloc.c,v 1.37 2008/11/23 10:09:25 mrg 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.37 2008/11/23 10:09:25 mrg 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%x, block = %lld, fs = %s\n", 533 ip->i_dev, (long long)bno, fs->e2fs_fsmnt); 534 panic("blkfree: freeing free block"); 535 } 536 clrbit(bbp, bno); 537 fs->e2fs.e2fs_fbcount++; 538 fs->e2fs_gd[cg].ext2bgd_nbfree++; 539 540 fs->e2fs_fmod = 1; 541 bdwrite(bp); 542 } 543 544 /* 545 * Free an inode. 546 * 547 * The specified inode is placed back in the free map. 548 */ 549 int 550 ext2fs_vfree(struct vnode *pvp, ino_t ino, int mode) 551 { 552 struct m_ext2fs *fs; 553 char *ibp; 554 struct inode *pip; 555 struct buf *bp; 556 int error, cg; 557 558 pip = VTOI(pvp); 559 fs = pip->i_e2fs; 560 if ((u_int)ino > fs->e2fs.e2fs_icount || (u_int)ino < EXT2_FIRSTINO) 561 panic("ifree: range: dev = 0x%x, ino = %llu, fs = %s", 562 pip->i_dev, (unsigned long long)ino, fs->e2fs_fsmnt); 563 cg = ino_to_cg(fs, ino); 564 error = bread(pip->i_devvp, 565 fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap), 566 (int)fs->e2fs_bsize, NOCRED, B_MODIFY, &bp); 567 if (error) { 568 brelse(bp, 0); 569 return (0); 570 } 571 ibp = (char *)bp->b_data; 572 ino = (ino - 1) % fs->e2fs.e2fs_ipg; 573 if (isclr(ibp, ino)) { 574 printf("dev = 0x%x, ino = %llu, fs = %s\n", 575 pip->i_dev, (unsigned long long)ino, fs->e2fs_fsmnt); 576 if (fs->e2fs_ronly == 0) 577 panic("ifree: freeing free inode"); 578 } 579 clrbit(ibp, ino); 580 fs->e2fs.e2fs_ficount++; 581 fs->e2fs_gd[cg].ext2bgd_nifree++; 582 if ((mode & IFMT) == IFDIR) { 583 fs->e2fs_gd[cg].ext2bgd_ndirs--; 584 } 585 fs->e2fs_fmod = 1; 586 bdwrite(bp); 587 return (0); 588 } 589 590 /* 591 * Find a block in the specified cylinder group. 592 * 593 * It is a panic if a request is made to find a block if none are 594 * available. 595 */ 596 597 static daddr_t 598 ext2fs_mapsearch(struct m_ext2fs *fs, char *bbp, daddr_t bpref) 599 { 600 daddr_t bno; 601 int start, len, loc, i, map; 602 603 /* 604 * find the fragment by searching through the free block 605 * map for an appropriate bit pattern 606 */ 607 if (bpref) 608 start = dtogd(fs, bpref) / NBBY; 609 else 610 start = 0; 611 len = howmany(fs->e2fs.e2fs_fpg, NBBY) - start; 612 loc = skpc(0xff, len, &bbp[start]); 613 if (loc == 0) { 614 len = start + 1; 615 start = 0; 616 loc = skpc(0xff, len, &bbp[start]); 617 if (loc == 0) { 618 printf("start = %d, len = %d, fs = %s\n", 619 start, len, fs->e2fs_fsmnt); 620 panic("ext2fs_alloccg: map corrupted"); 621 /* NOTREACHED */ 622 } 623 } 624 i = start + len - loc; 625 map = bbp[i]; 626 bno = i * NBBY; 627 for (i = 1; i < (1 << NBBY); i <<= 1, bno++) { 628 if ((map & i) == 0) 629 return (bno); 630 } 631 printf("fs = %s\n", fs->e2fs_fsmnt); 632 panic("ext2fs_mapsearch: block not in map"); 633 /* NOTREACHED */ 634 } 635 636 /* 637 * Fserr prints the name of a file system with an error diagnostic. 638 * 639 * The form of the error message is: 640 * fs: error message 641 */ 642 static void 643 ext2fs_fserr(struct m_ext2fs *fs, u_int uid, const char *cp) 644 { 645 646 log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->e2fs_fsmnt, cp); 647 } 648