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