Beispiel #1
0
/*
 * Stupid algorithm --- we now just search forward starting from the
 * goal.  Should put in a smarter one someday....
 */
errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
			   ext2fs_block_bitmap map, blk_t *ret)
{
	blk_t	i;

	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

	if (!map)
		map = fs->block_map;
	if (!map)
		return EXT2_ET_NO_BLOCK_BITMAP;
	if (!goal || (goal >= fs->super->s_blocks_count))
        //如果goal为0或者超过s_blocks_count,就使用第一个能用的block
		goal = fs->super->s_first_data_block;
	i = goal;
	do {
		if (!ext2fs_fast_test_block_bitmap(map, i)) {
            //如果map中的第i位空闲
			*ret = i;
			return 0;
		}
		i++;
		if (i >= fs->super->s_blocks_count)
			i = fs->super->s_first_data_block;
	} while (i != goal);
	return EXT2_ET_BLOCK_ALLOC_FAIL;
}
Beispiel #2
0
errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
				      ext2fs_block_bitmap bm2)
{
	int	i;
	
	EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_BLOCK_BITMAP);
	EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_BLOCK_BITMAP);

	if ((bm1->start != bm2->start) ||
	    (bm1->end != bm2->end) ||
	    (memcmp(bm1->bitmap, bm2->bitmap, (bm1->end - bm1->start)/8)))
		return EXT2_ET_NEQ_BLOCK_BITMAP;

	for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
		if (ext2fs_fast_test_block_bitmap(bm1, i) !=
		    ext2fs_fast_test_block_bitmap(bm2, i))
			return EXT2_ET_NEQ_BLOCK_BITMAP;

	return 0;
}
Beispiel #3
0
errcode_t ext2fs_compare_generic_bitmap(errcode_t magic, errcode_t neq,
					ext2fs_generic_bitmap bm1,
					ext2fs_generic_bitmap bm2)
{
	blk_t	i;

	if (!bm1 || bm1->magic != magic)
		return magic;
	if (!bm2 || bm2->magic != magic)
		return magic;

	if ((bm1->start != bm2->start) ||
	    (bm1->end != bm2->end) ||
	    (memcmp(bm1->bitmap, bm2->bitmap,
		    (size_t) (bm1->end - bm1->start)/8)))
		return neq;

	for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
		if (ext2fs_fast_test_block_bitmap(bm1, i) !=
		    ext2fs_fast_test_block_bitmap(bm2, i))
			return neq;

	return 0;
}
int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
				   blk_t block, int num)
{
	int	i;

	if ((block < bitmap->start) || (block+num-1 > bitmap->real_end)) {
		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
				   block, bitmap->description);
		return 0;
	}
	for (i=0; i < num; i++) {
		if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
			return 0;
	}
	return 1;
}
Beispiel #5
0
static void check_block_bitmaps(e2fsck_t ctx)
{
	ext2_filsys fs = ctx->fs;
	blk_t	i, super;
	int	*free_array;
	int	group = 0;
	unsigned int	blocks = 0;
	unsigned int	free_blocks = 0;
	int	group_free = 0;
	int	actual, bitmap;
	struct problem_context	pctx;
	int	problem, save_problem, fixit, had_problem;
	errcode_t	retval;
	int		lazy_bg = 0;
	int		skip_group = 0;

	clear_problem_context(&pctx);
	free_array = (int *) e2fsck_allocate_memory(ctx,
	    fs->group_desc_count * sizeof(int), "free block count array");

	if ((fs->super->s_first_data_block <
	     ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
	    (fs->super->s_blocks_count-1 >
	     ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
		pctx.num = 1;
		pctx.blk = fs->super->s_first_data_block;
		pctx.blk2 = fs->super->s_blocks_count -1;
		pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
		pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);

		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
		goto errout;
	}

	if ((fs->super->s_first_data_block <
	     ext2fs_get_block_bitmap_start(fs->block_map)) ||
	    (fs->super->s_blocks_count-1 >
	     ext2fs_get_block_bitmap_end(fs->block_map))) {
		pctx.num = 2;
		pctx.blk = fs->super->s_first_data_block;
		pctx.blk2 = fs->super->s_blocks_count -1;
		pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
		pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);

		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
		goto errout;
	}

	if (EXT2_HAS_COMPAT_FEATURE(fs->super, EXT2_FEATURE_COMPAT_LAZY_BG))
		lazy_bg++;

redo_counts:
	had_problem = 0;
	save_problem = 0;
	pctx.blk = pctx.blk2 = NO_BLK;
	if (lazy_bg && (fs->group_desc[group].bg_flags &
			EXT2_BG_BLOCK_UNINIT))
		skip_group++;
	super = fs->super->s_first_data_block;
	for (i = fs->super->s_first_data_block;
	     i < fs->super->s_blocks_count;
	     i++) {
		actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);

		if (skip_group) {
			if ((i >= super) &&
			    (i <= super + fs->desc_blocks) &&
			    ext2fs_bg_has_super(fs, group))
				bitmap = 1;
			else if (i == fs->group_desc[group].bg_block_bitmap)
				bitmap = 1;
			else if (i == fs->group_desc[group].bg_inode_bitmap)
				bitmap = 1;
			else if (i >= fs->group_desc[group].bg_inode_table &&
				 (i < fs->group_desc[group].bg_inode_table
				  + fs->inode_blocks_per_group))
				bitmap = 1;
			else
				bitmap = 0;
			actual = (actual != 0);
		} else
			bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);

		if (actual == bitmap)
			goto do_counts;

		if (!actual && bitmap) {
			/*
			 * Block not used, but marked in use in the bitmap.
			 */
			problem = PR_5_BLOCK_UNUSED;
		} else {
			/*
			 * Block used, but not marked in use in the bitmap.
			 */
			problem = PR_5_BLOCK_USED;
		}
		if (pctx.blk == NO_BLK) {
			pctx.blk = pctx.blk2 = i;
			save_problem = problem;
		} else {
			if ((problem == save_problem) &&
			    (pctx.blk2 == i-1))
				pctx.blk2++;
			else {
				print_bitmap_problem(ctx, save_problem, &pctx);
				pctx.blk = pctx.blk2 = i;
				save_problem = problem;
			}
		}
		ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
		had_problem++;

	do_counts:
		if (!bitmap && !skip_group) {
			group_free++;
			free_blocks++;
		}
		blocks ++;
		if ((blocks == fs->super->s_blocks_per_group) ||
		    (i == fs->super->s_blocks_count-1)) {
			free_array[group] = group_free;
			group ++;
			blocks = 0;
			group_free = 0;
			skip_group = 0;
			super += fs->super->s_blocks_per_group;
			if (ctx->progress)
				if ((ctx->progress)(ctx, 5, group,
						    fs->group_desc_count*2))
					goto errout;
			if (lazy_bg &&
			    (i != fs->super->s_blocks_count-1) &&
			    (fs->group_desc[group].bg_flags &
			     EXT2_BG_BLOCK_UNINIT))
				skip_group++;
		}
	}
	if (pctx.blk != NO_BLK)
		print_bitmap_problem(ctx, save_problem, &pctx);
	if (had_problem)
		fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
	else
		fixit = -1;
	ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;

	if (fixit == 1) {
		ext2fs_free_block_bitmap(fs->block_map);
		retval = ext2fs_copy_bitmap(ctx->block_found_map,
						  &fs->block_map);
		if (retval) {
			clear_problem_context(&pctx);
			fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
			ctx->flags |= E2F_FLAG_ABORT;
			goto errout;
		}
		ext2fs_set_bitmap_padding(fs->block_map);
		ext2fs_mark_bb_dirty(fs);

		/* Redo the counts */
		blocks = 0; free_blocks = 0; group_free = 0; group = 0;
		memset(free_array, 0, fs->group_desc_count * sizeof(int));
		goto redo_counts;
	} else if (fixit == 0)
		ext2fs_unmark_valid(fs);

	for (i = 0; i < fs->group_desc_count; i++) {
		if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
			pctx.group = i;
			pctx.blk = fs->group_desc[i].bg_free_blocks_count;
			pctx.blk2 = free_array[i];

			if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
					&pctx)) {
				fs->group_desc[i].bg_free_blocks_count =
					free_array[i];
				ext2fs_mark_super_dirty(fs);
			} else
				ext2fs_unmark_valid(fs);
		}
	}
	if (free_blocks != fs->super->s_free_blocks_count) {
		pctx.group = 0;
		pctx.blk = fs->super->s_free_blocks_count;
		pctx.blk2 = free_blocks;

		if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
			fs->super->s_free_blocks_count = free_blocks;
			ext2fs_mark_super_dirty(fs);
		} else
			ext2fs_unmark_valid(fs);
	}
errout:
	ext2fs_free_mem(&free_array);
}