almost all fsck errors fixed ("primary superblock features different from backup, check forced" left)

master
Vitaliy Filippov 2013-12-28 13:14:05 +00:00
parent a33f91e388
commit 97dc1bef18
1 changed files with 61 additions and 39 deletions

View File

@ -173,6 +173,7 @@ int shrink_move_inodes(realloc_data *rd)
{
goto out;
}
ext2fs_mark_ib_dirty(rd->fs);
// Remember mapping
realloc_add_inode_map(rd, ino, new_ino);
}
@ -238,7 +239,9 @@ int change_inode_numbers(realloc_data *rd)
int change_super_and_bgd(realloc_data *rd)
{
blk64_t it_start, blk;
dgrp_t grp, n_flex, last_grp;
dgrp_t grp, n_flex, n_grp;
__u32 unus;
int i_per_g_diff;
int flexbg_size = 0, i, retval = 0;
void *buf = NULL;
ext2fs_flush(rd->fs);
@ -255,14 +258,16 @@ int change_super_and_bgd(realloc_data *rd)
{
goto out;
}
i_per_g_diff = rd->new_inodes_per_group - EXT2_INODES_PER_GROUP(rd->fs->super);
for (n_flex = 0; n_flex < rd->fs->group_desc_count/flexbg_size; n_flex++)
{
last_grp = (n_flex+1)*flexbg_size;
if (last_grp > rd->fs->group_desc_count)
n_grp = flexbg_size;
if (n_flex*flexbg_size+n_grp > rd->fs->group_desc_count)
{
last_grp = rd->fs->group_desc_count;
n_grp = rd->fs->group_desc_count-n_flex*flexbg_size;
}
for (grp = n_flex*flexbg_size, i = 0; grp < last_grp; grp++, i++)
// Read inode tables
for (grp = n_flex*flexbg_size, i = 0; i < n_grp; grp++, i++)
{
if (!ext2fs_bg_flags_test(rd->fs, grp, EXT2_BG_INODE_UNINIT))
{
@ -275,37 +280,44 @@ int change_super_and_bgd(realloc_data *rd)
}
}
}
// Write inode table to the new place
it_start = ext2fs_inode_table_loc(rd->fs, n_flex*flexbg_size);
blk = rd->new_inode_blocks_per_group * (last_grp-n_flex*flexbg_size);
blk = rd->new_inode_blocks_per_group * n_grp;
retval = io_channel_write_blk64(rd->fs->io, it_start, blk, buf);
if (retval)
{
// The FS is badly corrupted now :-(
printf("Error moving inode tables for %u groups, starting from %u\n", last_grp-n_flex*flexbg_size, n_flex*flexbg_size);
printf("Error moving inode tables for %u groups, starting from %u\n", n_grp, n_flex*flexbg_size);
goto out;
}
// Mark/unmark extra inode table blocks
if (rd->new_inode_blocks_per_group < rd->fs->inode_blocks_per_group)
{
ext2fs_unmark_block_bitmap_range2(rd->fs->block_map, it_start+blk, (rd->fs->inode_blocks_per_group-rd->new_inode_blocks_per_group)*flexbg_size);
ext2fs_unmark_block_bitmap_range2(rd->fs->block_map, it_start+blk,
(rd->fs->inode_blocks_per_group-rd->new_inode_blocks_per_group)*n_grp);
}
else
{
ext2fs_mark_block_bitmap_range2(rd->fs->block_map, it_start+blk, (rd->new_inode_blocks_per_group-rd->fs->inode_blocks_per_group)*flexbg_size);
ext2fs_mark_block_bitmap_range2(rd->fs->block_map, it_start+blk,
(rd->new_inode_blocks_per_group-rd->fs->inode_blocks_per_group)*n_grp);
}
// Change inode table locations and free block/inode counts
for (grp = n_flex*flexbg_size, i = 0; grp < last_grp; grp++, i++)
if (!ext2fs_bg_flags_test(rd->fs, n_flex*flexbg_size, EXT2_BG_INODE_UNINIT))
{
if (!ext2fs_bg_flags_test(rd->fs, grp, EXT2_BG_INODE_UNINIT))
{
blk = it_start + rd->new_inode_blocks_per_group*i;
ext2fs_inode_table_loc_set(rd->fs, grp, blk);
ext2fs_bg_free_blocks_count_set(rd->fs, grp, ext2fs_bg_free_blocks_count(rd->fs, grp) +
rd->new_inode_blocks_per_group - rd->fs->inode_blocks_per_group);
ext2fs_bg_free_inodes_count_set(rd->fs, grp, ext2fs_bg_free_inodes_count(rd->fs, grp) +
rd->new_inodes_per_group - EXT2_INODES_PER_GROUP(rd->fs->super));
ext2fs_bg_itable_unused_set(rd->fs, grp, 0); // Is it correct?..
}
ext2fs_bg_free_blocks_count_set(rd->fs, n_flex*flexbg_size,
ext2fs_bg_free_blocks_count(rd->fs, n_flex*flexbg_size) -
(rd->new_inode_blocks_per_group - rd->fs->inode_blocks_per_group)*flexbg_size);
}
// Change inode table locations and free inode counts
for (grp = n_flex*flexbg_size, i = 0; i < n_grp; grp++, i++)
{
blk = it_start + rd->new_inode_blocks_per_group*i;
ext2fs_inode_table_loc_set(rd->fs, grp, blk);
ext2fs_bg_free_inodes_count_set(rd->fs, grp,
ext2fs_bg_free_inodes_count(rd->fs, grp) + i_per_g_diff);
unus = ext2fs_bg_itable_unused(rd->fs, grp);
unus = unus < i_per_g_diff ? 0 : unus - i_per_g_diff;
ext2fs_bg_itable_unused_set(rd->fs, grp, unus);
ext2fs_group_desc_csum_set(rd->fs, grp);
}
}
}
@ -314,31 +326,40 @@ int change_super_and_bgd(realloc_data *rd)
// Mark/unmark extra inode table blocks (without flex_bg)
for (grp = 0; grp < rd->fs->group_desc_count; grp++)
{
if (!ext2fs_bg_flags_test(rd->fs, grp, EXT2_BG_INODE_UNINIT))
it_start = ext2fs_inode_table_loc(rd->fs, grp);
if (rd->new_inode_blocks_per_group < rd->fs->inode_blocks_per_group)
{
it_start = ext2fs_inode_table_loc(rd->fs, grp);
if (rd->new_inode_blocks_per_group < rd->fs->inode_blocks_per_group)
{
ext2fs_unmark_block_bitmap_range2(rd->fs->block_map, it_start, rd->fs->inode_blocks_per_group-rd->new_inode_blocks_per_group);
}
else
{
ext2fs_mark_block_bitmap_range2(rd->fs->block_map, it_start, rd->new_inode_blocks_per_group-rd->fs->inode_blocks_per_group);
}
// Update free block/inode counts
ext2fs_bg_free_blocks_count_set(rd->fs, grp, ext2fs_bg_free_blocks_count(rd->fs, grp) +
rd->new_inode_blocks_per_group - rd->fs->inode_blocks_per_group);
ext2fs_bg_free_inodes_count_set(rd->fs, grp, ext2fs_bg_free_inodes_count(rd->fs, grp) +
rd->new_inodes_per_group - EXT2_INODES_PER_GROUP(rd->fs->super));
ext2fs_bg_itable_unused_set(rd->fs, grp, 0); // Is it correct?..
ext2fs_unmark_block_bitmap_range2(rd->fs->block_map, it_start,
rd->fs->inode_blocks_per_group-rd->new_inode_blocks_per_group);
}
else
{
ext2fs_mark_block_bitmap_range2(rd->fs->block_map, it_start,
rd->new_inode_blocks_per_group-rd->fs->inode_blocks_per_group);
}
ext2fs_bg_free_blocks_count_set(rd->fs, grp, ext2fs_bg_free_blocks_count(rd->fs, grp) -
rd->new_inode_blocks_per_group + rd->fs->inode_blocks_per_group);
ext2fs_bg_free_inodes_count_set(rd->fs, grp, ext2fs_bg_free_inodes_count(rd->fs, grp) +
rd->new_inodes_per_group - EXT2_INODES_PER_GROUP(rd->fs->super));
unus = ext2fs_bg_itable_unused(rd->fs, grp);
unus = unus < i_per_g_diff ? 0 : unus - i_per_g_diff;
ext2fs_bg_itable_unused_set(rd->fs, grp, unus);
ext2fs_group_desc_csum_set(rd->fs, grp);
}
}
}
ext2fs_free_blocks_count_add(rd->fs->super, rd->fs->group_desc_count * (rd->new_inode_blocks_per_group - rd->fs->inode_blocks_per_group));
ext2fs_mark_bb_dirty(rd->fs);
retval = rd->fs->write_bitmaps(rd->fs);
if (retval)
{
goto out;
}
rd->fs->write_bitmaps = NULL;
ext2fs_free_blocks_count_add(rd->fs->super, rd->fs->group_desc_count * (rd->fs->inode_blocks_per_group - rd->new_inode_blocks_per_group));
rd->fs->super->s_free_inodes_count += rd->fs->group_desc_count * (rd->new_inodes_per_group - EXT2_INODES_PER_GROUP(rd->fs->super));
rd->fs->super->s_inodes_per_group = rd->new_inodes_per_group;
rd->fs->super->s_inodes_count = rd->fs->group_desc_count * rd->new_inodes_per_group;
ext2fs_mark_super_dirty(rd->fs);
out:
if (buf)
{
@ -354,9 +375,10 @@ int do_realloc(realloc_data *rd)
{
int retval;
rd->new_inodes_per_group = rd->new_inode_count / rd->fs->group_desc_count;
rd->new_inodes_per_group &= ~7;
if (rd->new_inodes_per_group < 16)
{
printf("Too small number of inodes requested, min inodes per group = 16\n");
printf("Too small number of inodes requested (%u), min inodes per group = 16\n", rd->new_inodes_per_group);
return ENOENT;
}
rd->new_inode_blocks_per_group =