FreeBSD/sys/fs/ext2fs/ext2_alloc.c
/*
 * Determine whether a cluster can be allocated.
 */
Determine whether a cluster can be allocated.
Determine whether a cluster can be allocated .
static daddr_t
ext2_clusteralloc(struct inode *ip, int cg, daddr_t bpref, int len)
{
	struct m_ext2fs *fs;
	struct ext2mount *ump;
	struct buf *bp;
	char *bbp;
	int bit, error, got, i, loc, run;
	int32_t *lp;
	daddr_t bno;
	fs = ip->i_e2fs;
	ump = ip->i_ump;
	if (fs->e2fs_maxcluster[cg] < len)
		return (0);
	EXT2_UNLOCK(ump);
	error = bread(ip->i_devvp,
	    fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
	    (int)fs->e2fs_bsize, NOCRED, &bp);
	if (error)
		goto fail_lock;
	bbp = (char *)bp->b_data;
	EXT2_LOCK(ump);
	lp = &fs->e2fs_clustersum[cg].cs_sum[len];
	for (i = len; i <= fs->e2fs_contigsumsize; i++)
		if (*lp++ > 0)
			break;
	if (i > fs->e2fs_contigsumsize) {
		lp = &fs->e2fs_clustersum[cg].cs_sum[len - 1];
			for (i = len - 1; i > 0; i--)
				if (*lp-- > 0)
					break;
		fs->e2fs_maxcluster[cg] = i;
		goto fail;
	}
	EXT2_UNLOCK(ump);
	if (dtog(fs, bpref) != cg)
		bpref = 0;
	if (bpref != 0)
		bpref = dtogd(fs, bpref);
	loc = bpref / NBBY;
	bit = 1 << (bpref % NBBY);
	for (run = 0, got = bpref; got < fs->e2fs->e2fs_fpg; got++) {
		if ((bbp[loc] & bit) != 0)
			run = 0;
		else {
			run++;
			if (run == len)
				break;
		}
		if ((got & (NBBY - 1)) != (NBBY - 1))
			bit <<= 1;
		else {
			loc++;
			bit = 1;
		}
	}
	if (got >= fs->e2fs->e2fs_fpg)
		goto fail_lock;
	for (i = 1; i < len; i++)
		if (!isclr(bbp, got - run + i))
			panic("ext2_clusteralloc: map mismatch");
	bno = got - run + 1;
	if (bno >= fs->e2fs->e2fs_fpg)
		panic("ext2_clusteralloc: allocated out of group");
	EXT2_LOCK(ump);
	for (i = 0; i < len; i += fs->e2fs_fpb) {
		setbit(bbp, bno + i);
		ext2_clusteracct(fs, bbp, cg, bno + i, -1);
		fs->e2fs->e2fs_fbcount--;
		fs->e2fs_gd[cg].ext2bgd_nbfree--;
	}
	fs->e2fs_fmod = 1;
	EXT2_UNLOCK(ump);
	bdwrite(bp);
	return (cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno);
fail_lock:
	EXT2_LOCK(ump);
fail:
	brelse(bp);
	return (0);
}
static daddr_t ext2_clusteralloc ( struct inode * ip , int cg , daddr_t bpref , int len ) { struct m_ext2fs * fs ; struct ext2mount * ump ; struct buf * bp ; char * bbp ; int bit , error , got , i , loc , run ; int32_t * lp ; daddr_t bno ; fs = ip -> i_e2fs ; ump = ip -> i_ump ; if ( fs -> e2fs_maxcluster [ cg ] < len ) return ( 0 ) ; EXT2_UNLOCK ( ump ) ; error = bread ( ip -> i_devvp , fsbtodb ( fs , fs -> e2fs_gd [ cg ] . ext2bgd_b_bitmap ) , ( int ) fs -> e2fs_bsize , NOCRED , & bp ) ; if ( error ) goto fail_lock ; bbp = ( char * ) bp -> b_data ; EXT2_LOCK ( ump ) ; lp = & fs -> e2fs_clustersum [ cg ] . cs_sum [ len ] ; for ( i = len ; i <= fs -> e2fs_contigsumsize ; i ++ ) if ( * lp ++ > 0 ) break ; if ( i > fs -> e2fs_contigsumsize ) { lp = & fs -> e2fs_clustersum [ cg ] . cs_sum [ len - 1 ] ; for ( i = len - 1 ; i > 0 ; i -- ) if ( * lp -- > 0 ) break ; fs -> e2fs_maxcluster [ cg ] = i ; goto fail ; } EXT2_UNLOCK ( ump ) ; if ( dtog ( fs , bpref ) != cg ) bpref = 0 ; if ( bpref != 0 ) bpref = dtogd ( fs , bpref ) ; loc = bpref / NBBY ; bit = 1 << ( bpref % NBBY ) ; for ( run = 0 , got = bpref ; got < fs -> e2fs -> e2fs_fpg ; got ++ ) { if ( ( bbp [ loc ] & bit ) != 0 ) run = 0 ; else { run ++ ; if ( run == len ) break ; } if ( ( got & ( NBBY - 1 ) ) != ( NBBY - 1 ) ) bit <<= 1 ; else { loc ++ ; bit = 1 ; } } if ( got >= fs -> e2fs -> e2fs_fpg ) goto fail_lock ; for ( i = 1 ; i < len ; i ++ ) if ( ! isclr ( bbp , got - run + i ) ) panic ( " " ) ; bno = got - run + 1 ; if ( bno >= fs -> e2fs -> e2fs_fpg ) panic ( " " ) ; EXT2_LOCK ( ump ) ; for ( i = 0 ; i < len ; i += fs -> e2fs_fpb ) { setbit ( bbp , bno + i ) ; ext2_clusteracct ( fs , bbp , cg , bno + i , -1 ) ; fs -> e2fs -> e2fs_fbcount -- ; fs -> e2fs_gd [ cg ] . ext2bgd_nbfree -- ; } fs -> e2fs_fmod = 1 ; EXT2_UNLOCK ( ump ) ; bdwrite ( bp ) ; return ( cg * fs -> e2fs -> e2fs_fpg + fs -> e2fs -> e2fs_first_dblock + bno ) ; fail_lock : EXT2_LOCK ( ump ) ; fail : brelse ( bp ) ; return ( 0 ) ; }
Determine whether a cluster can be allocated.
Determine whether a cluster can be allocated .
/*
	 * Check to see if a cluster of the needed size (or bigger) is
	 * available in this cylinder group.
	 */ /*
		 * Update the cluster summary information to reflect
		 * the true maximum-sized cluster so that future cluster
		 * allocation requests can avoid reading the bitmap only
		 * to find no cluster.
		 */ /* Search the bitmap to find a big enough cluster like in FFS. */ /* Allocate the cluster that we found. */