Fix new algorithm; works now!
parent
2546396c10
commit
07da5e71d3
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue