mirror of https://github.com/vitalif/e2fsprogs
Remap blocks before moving inode tables (fixes big flex_bg extend),
check blocks to move even when shrinking inode tables (fixes big flex_bg shrink), mark inode tables during allocation (fixes bigalloc shrink)master
parent
152890aa45
commit
f58c260dc4
|
@ -367,9 +367,11 @@ static errcode_t resize_group_descriptors(ext2_resize_t rfs, blk64_t new_size)
|
||||||
* 4) block_mover(): move blocks out of the way as usual
|
* 4) block_mover(): move blocks out of the way as usual
|
||||||
* 5) inodes_to_move(): when shrinking inode tables, move inodes from the end
|
* 5) inodes_to_move(): when shrinking inode tables, move inodes from the end
|
||||||
* of each group's inode table (still operating on old fs inode tables).
|
* of each group's inode table (still operating on old fs inode tables).
|
||||||
* rewrite blocks used by inodes.
|
* it would be possible to rewrite blocks on step 7, but we need to read
|
||||||
|
* extents, and they may be overwritten by inode tables on step 6.
|
||||||
|
* so, rewrite blocks used by inodes here!
|
||||||
* 6) move_inode_tables(): move inode tables
|
* 6) move_inode_tables(): move inode tables
|
||||||
* 7) inode_scan_and_fix(): rewrite all extent checksums, extattr and ACL checksums
|
* 7) inode_scan_and_fix(): rewrite all inode, extent, extattr and ACL checksums
|
||||||
* 8) inode_ref_fix(): translate inode numbers (operating on new fs inode tables)
|
* 8) inode_ref_fix(): translate inode numbers (operating on new fs inode tables)
|
||||||
*/
|
*/
|
||||||
static int set_inode_count(ext2_filsys fs, __u32 new_inodes)
|
static int set_inode_count(ext2_filsys fs, __u32 new_inodes)
|
||||||
|
@ -1366,17 +1368,17 @@ static errcode_t blocks_to_move(ext2_resize_t rfs)
|
||||||
if (retval) {
|
if (retval) {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
// If we're extending inode tables, we need to move some blocks away
|
ext2fs_mark_block_bitmap_range2(empty_bmap,
|
||||||
if (rfs->old_fs->inode_blocks_per_group < fs->inode_blocks_per_group) {
|
ext2fs_inode_table_loc(fs, g), fs->inode_blocks_per_group);
|
||||||
group_blk = ext2fs_inode_table_loc(fs, g)+fs->inode_blocks_per_group;
|
// We may need to move some blocks away (mainly if extending inode tables)
|
||||||
for (blk = ext2fs_inode_table_loc(fs, g); blk < group_blk; blk++) {
|
group_blk = ext2fs_inode_table_loc(fs, g)+fs->inode_blocks_per_group;
|
||||||
if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
|
for (blk = ext2fs_inode_table_loc(fs, g); blk < group_blk; blk++) {
|
||||||
!ext2fs_test_block_bitmap2(meta_bmap, blk)) {
|
if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
|
||||||
ext2fs_mark_block_bitmap2(rfs->move_blocks, blk);
|
!ext2fs_test_block_bitmap2(meta_bmap, blk)) {
|
||||||
rfs->needed_blocks++;
|
ext2fs_mark_block_bitmap2(rfs->move_blocks, blk);
|
||||||
}
|
rfs->needed_blocks++;
|
||||||
ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
|
|
||||||
}
|
}
|
||||||
|
ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ext2fs_free_block_bitmap(empty_bmap);
|
ext2fs_free_block_bitmap(empty_bmap);
|
||||||
|
@ -1941,7 +1943,7 @@ static int process_block(ext2_filsys fs, blk64_t *block_nr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pb->is_dir) {
|
if (pb->is_dir && fs->dblist) {
|
||||||
retval = ext2fs_add_dir_block2(fs->dblist, pb->ino,
|
retval = ext2fs_add_dir_block2(fs->dblist, pb->ino,
|
||||||
block, (int) blockcnt);
|
block, (int) blockcnt);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
|
@ -2084,18 +2086,22 @@ static void quiet_com_err_proc(const char *whoami EXT2FS_ATTR((unused)),
|
||||||
|
|
||||||
static errcode_t inodes_to_move(ext2_resize_t rfs)
|
static errcode_t inodes_to_move(ext2_resize_t rfs)
|
||||||
{
|
{
|
||||||
|
struct process_block_struct pb;
|
||||||
ext2_ino_t ino, new_inode, tr_ino;
|
ext2_ino_t ino, new_inode, tr_ino;
|
||||||
struct ext2_inode *inode = NULL;
|
struct ext2_inode *inode = NULL;
|
||||||
ext2_inode_scan scan = NULL;
|
ext2_inode_scan scan = NULL;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
dgrp_t g, old_g;
|
dgrp_t g, old_g;
|
||||||
|
char *block_buf = 0;
|
||||||
ext2_ino_t start_to_move;
|
ext2_ino_t start_to_move;
|
||||||
int inode_size;
|
int inode_size;
|
||||||
int shrink_inodes = rfs->old_fs->inode_blocks_per_group > rfs->new_fs->inode_blocks_per_group;
|
int shrink_inodes = rfs->old_fs->inode_blocks_per_group > rfs->new_fs->inode_blocks_per_group;
|
||||||
|
int change_inodes = rfs->old_fs->inode_blocks_per_group != rfs->new_fs->inode_blocks_per_group;
|
||||||
|
|
||||||
if ((rfs->old_fs->group_desc_count <=
|
if ((rfs->old_fs->group_desc_count <=
|
||||||
rfs->new_fs->group_desc_count) &&
|
rfs->new_fs->group_desc_count) &&
|
||||||
!shrink_inodes)
|
!rfs->bmap &&
|
||||||
|
!change_inodes)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan);
|
retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan);
|
||||||
|
@ -2115,12 +2121,18 @@ static errcode_t inodes_to_move(ext2_resize_t rfs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retval = ext2fs_get_array(rfs->new_fs->blocksize, 3, &block_buf);
|
||||||
|
if (retval) goto errout;
|
||||||
|
|
||||||
inode_size = EXT2_INODE_SIZE(rfs->new_fs->super);
|
inode_size = EXT2_INODE_SIZE(rfs->new_fs->super);
|
||||||
inode = malloc(inode_size);
|
inode = malloc(inode_size);
|
||||||
if (!inode) {
|
if (!inode) {
|
||||||
retval = ENOMEM;
|
retval = ENOMEM;
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
pb.rfs = rfs;
|
||||||
|
pb.inode = inode;
|
||||||
|
pb.error = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First, copy all of the inodes that need to be moved
|
* First, copy all of the inodes that need to be moved
|
||||||
|
@ -2179,12 +2191,43 @@ static errcode_t inodes_to_move(ext2_resize_t rfs)
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
ext2fs_add_extent_entry(rfs->imap, ino, new_inode);
|
ext2fs_add_extent_entry(rfs->imap, ino, new_inode);
|
||||||
|
|
||||||
|
// continue with rewritten inode number
|
||||||
|
ino = new_inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update inodes to point to new blocks.
|
||||||
|
*/
|
||||||
|
pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
|
||||||
|
if (ext2fs_inode_has_valid_blocks2(rfs->old_fs, inode) && rfs->bmap) {
|
||||||
|
pb.changed = 0;
|
||||||
|
pb.ino = ino;
|
||||||
|
pb.old_ino = ino; // FIXME debug output will show translated inodes
|
||||||
|
pb.has_extents = inode->i_flags & EXT4_EXTENTS_FL;
|
||||||
|
rfs->old_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
|
retval = ext2fs_block_iterate3(rfs->old_fs,
|
||||||
|
ino, 0, block_buf,
|
||||||
|
process_block, &pb);
|
||||||
|
rfs->old_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
|
if (retval)
|
||||||
|
goto errout;
|
||||||
|
if (pb.error) {
|
||||||
|
retval = pb.error;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
|
if (rfs->bmap) {
|
||||||
|
ext2fs_free_extent_table(rfs->bmap);
|
||||||
|
rfs->bmap = 0;
|
||||||
|
}
|
||||||
if (scan)
|
if (scan)
|
||||||
ext2fs_close_inode_scan(scan);
|
ext2fs_close_inode_scan(scan);
|
||||||
|
if (block_buf)
|
||||||
|
ext2fs_free_mem(&block_buf);
|
||||||
free(inode);
|
free(inode);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -2198,13 +2241,11 @@ static errcode_t inode_scan_and_fix(ext2_resize_t rfs)
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
dgrp_t g;
|
dgrp_t g;
|
||||||
char *block_buf = 0;
|
char *block_buf = 0;
|
||||||
ext2_ino_t start_to_move;
|
|
||||||
int inode_size;
|
int inode_size;
|
||||||
int change_inodes = rfs->old_fs->inode_blocks_per_group != rfs->new_fs->inode_blocks_per_group;
|
int change_inodes = rfs->old_fs->inode_blocks_per_group != rfs->new_fs->inode_blocks_per_group;
|
||||||
|
|
||||||
if ((rfs->old_fs->group_desc_count <=
|
if ((rfs->old_fs->group_desc_count <=
|
||||||
rfs->new_fs->group_desc_count) &&
|
rfs->new_fs->group_desc_count) &&
|
||||||
!rfs->bmap &&
|
|
||||||
!change_inodes)
|
!change_inodes)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -2225,15 +2266,15 @@ static errcode_t inode_scan_and_fix(ext2_resize_t rfs)
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs);
|
ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs);
|
||||||
pb.rfs = rfs;
|
|
||||||
pb.inode = inode;
|
|
||||||
pb.error = 0;
|
|
||||||
inode_size = EXT2_INODE_SIZE(rfs->new_fs->super);
|
inode_size = EXT2_INODE_SIZE(rfs->new_fs->super);
|
||||||
inode = malloc(inode_size);
|
inode = malloc(inode_size);
|
||||||
if (!inode) {
|
if (!inode) {
|
||||||
retval = ENOMEM;
|
retval = ENOMEM;
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
pb.rfs = rfs;
|
||||||
|
pb.inode = inode;
|
||||||
|
pb.error = 0;
|
||||||
/*
|
/*
|
||||||
* First, copy all of the inodes that need to be moved
|
* First, copy all of the inodes that need to be moved
|
||||||
* elsewhere in the inode table
|
* elsewhere in the inode table
|
||||||
|
@ -2276,12 +2317,10 @@ remap_blocks:
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update inodes to point to new blocks; schedule directory
|
* Schedule directory blocks for inode remapping. Need to write out dir blocks
|
||||||
* blocks for inode remapping. Need to write out dir blocks
|
|
||||||
* with new inode numbers if we have metadata_csum enabled.
|
* with new inode numbers if we have metadata_csum enabled.
|
||||||
*/
|
*/
|
||||||
if (ext2fs_inode_has_valid_blocks2(rfs->new_fs, inode) &&
|
if (ext2fs_inode_has_valid_blocks2(rfs->new_fs, inode) && pb.is_dir) {
|
||||||
(rfs->bmap || pb.is_dir)) {
|
|
||||||
pb.ino = ino;
|
pb.ino = ino;
|
||||||
pb.old_ino = ino; // FIXME: Debug output will show translated inodes
|
pb.old_ino = ino; // FIXME: Debug output will show translated inodes
|
||||||
pb.has_extents = inode->i_flags & EXT4_EXTENTS_FL;
|
pb.has_extents = inode->i_flags & EXT4_EXTENTS_FL;
|
||||||
|
@ -2296,8 +2335,7 @@ remap_blocks:
|
||||||
retval = pb.error;
|
retval = pb.error;
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
} else if ((inode->i_flags & EXT4_INLINE_DATA_FL) &&
|
} else if ((inode->i_flags & EXT4_INLINE_DATA_FL) && pb.is_dir) {
|
||||||
(rfs->bmap || pb.is_dir)) {
|
|
||||||
/* inline data dir; update it too */
|
/* inline data dir; update it too */
|
||||||
retval = ext2fs_add_dir_block2(rfs->new_fs->dblist,
|
retval = ext2fs_add_dir_block2(rfs->new_fs->dblist,
|
||||||
tr_ino, 0, 0);
|
tr_ino, 0, 0);
|
||||||
|
@ -2309,10 +2347,6 @@ remap_blocks:
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
reset_com_err_hook();
|
reset_com_err_hook();
|
||||||
if (rfs->bmap) {
|
|
||||||
ext2fs_free_extent_table(rfs->bmap);
|
|
||||||
rfs->bmap = 0;
|
|
||||||
}
|
|
||||||
if (scan)
|
if (scan)
|
||||||
ext2fs_close_inode_scan(scan);
|
ext2fs_close_inode_scan(scan);
|
||||||
if (block_buf)
|
if (block_buf)
|
||||||
|
@ -2360,10 +2394,13 @@ static errcode_t move_inode_tables(ext2_resize_t rfs)
|
||||||
ext2fs_bg_free_inodes_count(rfs->new_fs, g) + new_ipg - old_ipg);
|
ext2fs_bg_free_inodes_count(rfs->new_fs, g) + new_ipg - old_ipg);
|
||||||
ext2fs_group_desc_csum_set(rfs->new_fs, g);
|
ext2fs_group_desc_csum_set(rfs->new_fs, g);
|
||||||
}
|
}
|
||||||
printf("g%u = %u->%u free=%u unused=%u\n", g,
|
printf("g%u = [%u?] %u->%u free=%u->%u unused=%u->%u\n", g,
|
||||||
|
g > 0 ? ext2fs_inode_table_loc(rfs->old_fs, g-1)+old_ibg : 0,
|
||||||
ext2fs_inode_table_loc(rfs->old_fs, g),
|
ext2fs_inode_table_loc(rfs->old_fs, g),
|
||||||
ext2fs_inode_table_loc(rfs->new_fs, g),
|
ext2fs_inode_table_loc(rfs->new_fs, g),
|
||||||
|
ext2fs_bg_free_inodes_count(rfs->old_fs, g),
|
||||||
ext2fs_bg_free_inodes_count(rfs->new_fs, g),
|
ext2fs_bg_free_inodes_count(rfs->new_fs, g),
|
||||||
|
ext2fs_bg_itable_unused(rfs->old_fs, g),
|
||||||
ext2fs_bg_itable_unused(rfs->new_fs, g));
|
ext2fs_bg_itable_unused(rfs->new_fs, g));
|
||||||
if ((change_inodes || ext2fs_inode_table_loc(rfs->new_fs, g) != ext2fs_inode_table_loc(rfs->old_fs, g)) &&
|
if ((change_inodes || ext2fs_inode_table_loc(rfs->new_fs, g) != ext2fs_inode_table_loc(rfs->old_fs, g)) &&
|
||||||
(!ext2fs_has_group_desc_csum(rfs->new_fs) ||
|
(!ext2fs_has_group_desc_csum(rfs->new_fs) ||
|
||||||
|
|
Loading…
Reference in New Issue