Fix new algorithm; works now!

master
Vitaliy Filippov 2014-01-09 21:29:10 +00:00
parent 2546396c10
commit 07da5e71d3
1 changed files with 33 additions and 17 deletions

View File

@ -22,9 +22,7 @@
/**
* TODO bigalloc compatibility
* TODO write some tests: for inode moving (image with many files),
* for block moving, including extent blocks (one sparse file with many extents),
* for block moving between different groups
* TODO write some tests
*
* The theory isn't that hard:
* 1) Determine where we want to move the inode tables:
@ -64,6 +62,17 @@
* also using e2patch utility.
*/
/**
* Need tests for:
* - both ext2 and ext4 filesystem images
* - inode moving: FS image with many files
* - block moving, including extent blocks: big sparse file with many extents
* - block moving between different groups
* - reallocation (both shrink and grow) in case of big flex_bg when inode
* tables don't fit into single block group
* - non-optimal reallocation, i.e. when inode block count doesn't change
*/
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
@ -241,8 +250,8 @@ out:
}
/**
* Move data blocks from after the end of each block group inode table
* so the tables can be grown
* Move data blocks from the new place for each block group inode table
* so the tables can be grown or moved.
*/
errcode_t extend_move_blocks(realloc_data *rd)
{
@ -332,6 +341,7 @@ errcode_t change_super_and_bgd(realloc_data *rd)
{
goto out;
}
// First mark/unmark inode table blocks (mark and unmark in separate passes)
for (grp = 0; grp < rd->fs->group_desc_count; grp++)
{
for (i = 0, blk = ext2fs_inode_table_loc(rd->fs, grp); i < rd->ibg_old; i++, blk++)
@ -343,7 +353,13 @@ errcode_t change_super_and_bgd(realloc_data *rd)
{
for (i = 0, blk = rd->new_itable_loc[grp]; i < rd->ibg_new; i++, blk++)
{
ext2fs_block_alloc_stats2(rd->fs, blk, -1);
if (ext2fs_test_block_bitmap2(rd->fs->block_map, blk))
{
printf("BUG: Block %lld (suited for group %u inode table) is still allocated\n", blk, grp);
retval = ENOSPC;
goto out;
}
ext2fs_block_alloc_stats2(rd->fs, blk, +1);
}
}
for (grp = 0; grp < rd->fs->group_desc_count; grp++)
@ -411,7 +427,6 @@ errcode_t change_super_and_bgd(realloc_data *rd)
rd->fs->write_bitmaps = NULL;
// Explicitly set 'overwrite backup superblocks' flag
rd->fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
ext2fs_free_blocks_count_add(rd->fs->super, rd->fs->group_desc_count * (rd->ibg_old - rd->ibg_new));
rd->fs->super->s_free_inodes_count += rd->fs->group_desc_count * (rd->ig_new - rd->ig_old);
rd->fs->super->s_inodes_per_group = rd->ig_new;
rd->fs->super->s_inodes_count = rd->fs->group_desc_count * rd->ig_new;
@ -526,6 +541,7 @@ errcode_t do_realloc(realloc_data *rd)
{
__u32 ig_round;
errcode_t retval;
int phase = 1;
rd->ig_old = EXT2_INODES_PER_GROUP(rd->fs->super);
rd->ig_new = rd->new_inode_count / rd->fs->group_desc_count;
// inodes-per-group must be a multiple of 8 so each byte of inode bitmap is filled
@ -565,7 +581,7 @@ errcode_t do_realloc(realloc_data *rd)
rd->fs->super->s_inodes_count - rd->fs->super->s_free_inodes_count);
return ENOENT;
}
printf("Phase 1: Moving inodes out of the way\n");
printf("Phase %d: Moving inodes out of the way\n", phase++);
retval = shrink_move_inodes(rd);
if (retval)
{
@ -582,25 +598,25 @@ errcode_t do_realloc(realloc_data *rd)
required_blocks, ext2fs_free_blocks_count(rd->fs->super));
return ENOENT;
}
printf("Phase 1: Moving data blocks out of the way\n");
retval = extend_move_blocks(rd);
if (retval)
{
return retval;
}
}
else
else if (rd->ibg_new == rd->ibg_old)
{
printf("The requested number of inodes is equal to current\n");
return 0;
}
printf("Phase 2: Changing all inode numbers\n");
printf("Phase %d: Moving data blocks out of the way\n", phase++);
retval = extend_move_blocks(rd);
if (retval)
{
return retval;
}
printf("Phase %d: Changing all inode numbers\n", phase++);
retval = change_inode_numbers(rd);
if (retval)
{
return retval;
}
printf("Phase 3: Adjusting superblock and block group descriptors\n");
printf("Phase %d: Adjusting superblock and block group descriptors\n", phase++);
retval = change_super_and_bgd(rd);
if (retval)
{