Fix new algorithm; works now!
parent
2546396c10
commit
07da5e71d3
|
@ -22,9 +22,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO bigalloc compatibility
|
* TODO bigalloc compatibility
|
||||||
* TODO write some tests: for inode moving (image with many files),
|
* TODO write some tests
|
||||||
* for block moving, including extent blocks (one sparse file with many extents),
|
|
||||||
* for block moving between different groups
|
|
||||||
*
|
*
|
||||||
* The theory isn't that hard:
|
* The theory isn't that hard:
|
||||||
* 1) Determine where we want to move the inode tables:
|
* 1) Determine where we want to move the inode tables:
|
||||||
|
@ -64,6 +62,17 @@
|
||||||
* also using e2patch utility.
|
* 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 <stdio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -241,8 +250,8 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move data blocks from after the end of each block group inode table
|
* Move data blocks from the new place for each block group inode table
|
||||||
* so the tables can be grown
|
* so the tables can be grown or moved.
|
||||||
*/
|
*/
|
||||||
errcode_t extend_move_blocks(realloc_data *rd)
|
errcode_t extend_move_blocks(realloc_data *rd)
|
||||||
{
|
{
|
||||||
|
@ -332,6 +341,7 @@ errcode_t change_super_and_bgd(realloc_data *rd)
|
||||||
{
|
{
|
||||||
goto out;
|
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 (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++)
|
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++)
|
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++)
|
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;
|
rd->fs->write_bitmaps = NULL;
|
||||||
// Explicitly set 'overwrite backup superblocks' flag
|
// Explicitly set 'overwrite backup superblocks' flag
|
||||||
rd->fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
|
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_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_per_group = rd->ig_new;
|
||||||
rd->fs->super->s_inodes_count = rd->fs->group_desc_count * 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;
|
__u32 ig_round;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
|
int phase = 1;
|
||||||
rd->ig_old = EXT2_INODES_PER_GROUP(rd->fs->super);
|
rd->ig_old = EXT2_INODES_PER_GROUP(rd->fs->super);
|
||||||
rd->ig_new = rd->new_inode_count / rd->fs->group_desc_count;
|
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
|
// 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);
|
rd->fs->super->s_inodes_count - rd->fs->super->s_free_inodes_count);
|
||||||
return ENOENT;
|
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);
|
retval = shrink_move_inodes(rd);
|
||||||
if (retval)
|
if (retval)
|
||||||
{
|
{
|
||||||
|
@ -582,25 +598,25 @@ errcode_t do_realloc(realloc_data *rd)
|
||||||
required_blocks, ext2fs_free_blocks_count(rd->fs->super));
|
required_blocks, ext2fs_free_blocks_count(rd->fs->super));
|
||||||
return ENOENT;
|
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");
|
printf("The requested number of inodes is equal to current\n");
|
||||||
return 0;
|
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);
|
retval = change_inode_numbers(rd);
|
||||||
if (retval)
|
if (retval)
|
||||||
{
|
{
|
||||||
return 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);
|
retval = change_super_and_bgd(rd);
|
||||||
if (retval)
|
if (retval)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue