summaryrefslogtreecommitdiff
path: root/lib/ext2fs/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ext2fs/alloc.c')
-rw-r--r--lib/ext2fs/alloc.c86
1 files changed, 23 insertions, 63 deletions
diff --git a/lib/ext2fs/alloc.c b/lib/ext2fs/alloc.c
index 775dfcc4..0acbc4e6 100644
--- a/lib/ext2fs/alloc.c
+++ b/lib/ext2fs/alloc.c
@@ -27,50 +27,17 @@
#include "ext2fs.h"
/*
- * Check for uninit block bitmaps and deal with them appropriately
+ * Clear the uninit block bitmap flag if necessary
*/
-static void check_block_uninit(ext2_filsys fs, ext2fs_block_bitmap map,
- dgrp_t group)
+static void clear_block_uninit(ext2_filsys fs, dgrp_t group)
{
- blk_t i;
- blk64_t blk, super_blk, old_desc_blk, new_desc_blk;
- int old_desc_blocks;
-
if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) ||
!(ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
return;
- blk = (group * fs->super->s_blocks_per_group) +
- fs->super->s_first_data_block;
-
- ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
- &old_desc_blk, &new_desc_blk, 0);
-
- if (fs->super->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_META_BG)
- old_desc_blocks = fs->super->s_first_meta_bg;
- else
- old_desc_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
-
- for (i=0; i < fs->super->s_blocks_per_group; i++, blk++)
- ext2fs_fast_unmark_block_bitmap2(map, blk);
-
- blk = (group * fs->super->s_blocks_per_group) +
- fs->super->s_first_data_block;
- for (i=0; i < fs->super->s_blocks_per_group; i++, blk++) {
- if ((blk == super_blk) ||
- (old_desc_blk && old_desc_blocks &&
- (blk >= old_desc_blk) &&
- (blk < old_desc_blk + old_desc_blocks)) ||
- (new_desc_blk && (blk == new_desc_blk)) ||
- (blk == ext2fs_block_bitmap_loc(fs, group)) ||
- (blk == ext2fs_inode_bitmap_loc(fs, group)) ||
- (blk >= ext2fs_inode_table_loc(fs, group) &&
- (blk < ext2fs_inode_table_loc(fs, group)
- + fs->inode_blocks_per_group)))
- ext2fs_fast_mark_block_bitmap2(map, blk);
- }
+ /* uninit block bitmaps are now initialized in read_bitmaps() */
+
ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, group);
ext2fs_mark_super_dirty(fs);
@@ -95,10 +62,11 @@ static void check_inode_uninit(ext2_filsys fs, ext2fs_inode_bitmap map,
ext2fs_fast_unmark_inode_bitmap2(map, ino);
ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
+ /* Mimics what the kernel does */
+ ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, group);
ext2fs_mark_ib_dirty(fs);
ext2fs_mark_super_dirty(fs);
- check_block_uninit(fs, fs->block_map, group);
}
/*
@@ -169,8 +137,8 @@ errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal,
ext2fs_block_bitmap map, blk64_t *ret)
{
- blk64_t i;
- int c_ratio;
+ errcode_t retval;
+ blk64_t b = 0;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
@@ -180,29 +148,21 @@ errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal,
return EXT2_ET_NO_BLOCK_BITMAP;
if (!goal || (goal >= ext2fs_blocks_count(fs->super)))
goal = fs->super->s_first_data_block;
- i = goal;
- c_ratio = 1 << ext2fs_get_bitmap_granularity(map);
- if (c_ratio > 1)
- goal &= ~EXT2FS_CLUSTER_MASK(fs);
- check_block_uninit(fs, map,
- (i - fs->super->s_first_data_block) /
- EXT2_BLOCKS_PER_GROUP(fs->super));
- do {
- if (((i - fs->super->s_first_data_block) %
- EXT2_BLOCKS_PER_GROUP(fs->super)) == 0)
- check_block_uninit(fs, map,
- (i - fs->super->s_first_data_block) /
- EXT2_BLOCKS_PER_GROUP(fs->super));
-
- if (!ext2fs_fast_test_block_bitmap2(map, i)) {
- *ret = i;
- return 0;
- }
- i = (i + c_ratio) & ~(c_ratio - 1);
- if (i >= ext2fs_blocks_count(fs->super))
- i = fs->super->s_first_data_block;
- } while (i != goal);
- return EXT2_ET_BLOCK_ALLOC_FAIL;
+ goal &= ~EXT2FS_CLUSTER_MASK(fs);
+
+ retval = ext2fs_find_first_zero_block_bitmap2(map,
+ goal, ext2fs_blocks_count(fs->super) - 1, &b);
+ if ((retval == ENOENT) && (goal != fs->super->s_first_data_block))
+ retval = ext2fs_find_first_zero_block_bitmap2(map,
+ fs->super->s_first_data_block, goal - 1, &b);
+ if (retval == ENOENT)
+ return EXT2_ET_BLOCK_ALLOC_FAIL;
+ if (retval)
+ return retval;
+
+ clear_block_uninit(fs, ext2fs_group_of_blk2(fs, b));
+ *ret = b;
+ return 0;
}
errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,