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; goto out;
} }
ext2fs_mark_ib_dirty(rd->fs);
// Remember mapping // Remember mapping
realloc_add_inode_map(rd, ino, new_ino); 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) int change_super_and_bgd(realloc_data *rd)
{ {
blk64_t it_start, blk; 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; int flexbg_size = 0, i, retval = 0;
void *buf = NULL; void *buf = NULL;
ext2fs_flush(rd->fs); ext2fs_flush(rd->fs);
@ -255,14 +258,16 @@ int change_super_and_bgd(realloc_data *rd)
{ {
goto out; 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++) for (n_flex = 0; n_flex < rd->fs->group_desc_count/flexbg_size; n_flex++)
{ {
last_grp = (n_flex+1)*flexbg_size; n_grp = flexbg_size;
if (last_grp > rd->fs->group_desc_count) 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)) 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); 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); retval = io_channel_write_blk64(rd->fs->io, it_start, blk, buf);
if (retval) if (retval)
{ {
// The FS is badly corrupted now :-( // 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; goto out;
} }
// Mark/unmark extra inode table blocks // Mark/unmark extra inode table blocks
if (rd->new_inode_blocks_per_group < rd->fs->inode_blocks_per_group) 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 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 if (!ext2fs_bg_flags_test(rd->fs, n_flex*flexbg_size, EXT2_BG_INODE_UNINIT))
for (grp = n_flex*flexbg_size, i = 0; grp < last_grp; grp++, i++)
{ {
if (!ext2fs_bg_flags_test(rd->fs, grp, EXT2_BG_INODE_UNINIT)) ext2fs_bg_free_blocks_count_set(rd->fs, n_flex*flexbg_size,
{ ext2fs_bg_free_blocks_count(rd->fs, n_flex*flexbg_size) -
blk = it_start + rd->new_inode_blocks_per_group*i; (rd->new_inode_blocks_per_group - rd->fs->inode_blocks_per_group)*flexbg_size);
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) + // Change inode table locations and free inode counts
rd->new_inode_blocks_per_group - rd->fs->inode_blocks_per_group); for (grp = n_flex*flexbg_size, i = 0; i < n_grp; grp++, i++)
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)); blk = it_start + rd->new_inode_blocks_per_group*i;
ext2fs_bg_itable_unused_set(rd->fs, grp, 0); // Is it correct?.. 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) // Mark/unmark extra inode table blocks (without flex_bg)
for (grp = 0; grp < rd->fs->group_desc_count; grp++) 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); ext2fs_unmark_block_bitmap_range2(rd->fs->block_map, it_start,
if (rd->new_inode_blocks_per_group < rd->fs->inode_blocks_per_group) rd->fs->inode_blocks_per_group-rd->new_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?..
} }
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_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_per_group = rd->new_inodes_per_group;
rd->fs->super->s_inodes_count = rd->fs->group_desc_count * 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: out:
if (buf) if (buf)
{ {
@ -354,9 +375,10 @@ int do_realloc(realloc_data *rd)
{ {
int retval; int retval;
rd->new_inodes_per_group = rd->new_inode_count / rd->fs->group_desc_count; 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) 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; return ENOENT;
} }
rd->new_inode_blocks_per_group = rd->new_inode_blocks_per_group =