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