fix inode checksums... but it also requires to fix directory checksums... so in fact it is better to just merge it in resize2fs...
parent
ceeb9c6cdc
commit
bf188ee362
7
bmove.c
7
bmove.c
|
@ -161,6 +161,13 @@ errcode_t ext2fs_move_blocks(ext2_filsys fs,
|
||||||
|
|
||||||
pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) && flags & EXT2_BMOVE_GET_DBLIST);
|
pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) && flags & EXT2_BMOVE_GET_DBLIST);
|
||||||
|
|
||||||
|
if ((inode.i_flags & EXT4_INLINE_DATA_FL) && pb.add_dir) {
|
||||||
|
/* inline data dir; update it too */
|
||||||
|
retval = ext2fs_add_dir_block2(fs->dblist, ino, 0, 0);
|
||||||
|
if (retval)
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
retval = ext2fs_block_iterate3(fs, ino, 0, block_buf, process_block, &pb);
|
retval = ext2fs_block_iterate3(fs, ino, 0, block_buf, process_block, &pb);
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
118
realloc-inodes.c
118
realloc-inodes.c
|
@ -119,6 +119,7 @@
|
||||||
EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\
|
EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\
|
||||||
EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\
|
EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\
|
||||||
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|\
|
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|\
|
||||||
|
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\
|
||||||
EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\
|
EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\
|
||||||
EXT4_FEATURE_RO_COMPAT_BIGALLOC|\
|
EXT4_FEATURE_RO_COMPAT_BIGALLOC|\
|
||||||
EXT4_FEATURE_RO_COMPAT_QUOTA)
|
EXT4_FEATURE_RO_COMPAT_QUOTA)
|
||||||
|
@ -202,6 +203,59 @@ ext2_ino_t realloc_search_inode_map(realloc_data *rd, ext2_ino_t old)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Rewrite extents */
|
||||||
|
static errcode_t rewrite_extents(ext2_filsys fs, ext2_ino_t ino)
|
||||||
|
{
|
||||||
|
ext2_extent_handle_t handle;
|
||||||
|
struct ext2fs_extent extent;
|
||||||
|
errcode_t errcode;
|
||||||
|
struct ext2_extent_info info;
|
||||||
|
|
||||||
|
errcode = ext2fs_extent_open(fs, ino, &handle);
|
||||||
|
if (errcode)
|
||||||
|
return errcode;
|
||||||
|
|
||||||
|
errcode = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent);
|
||||||
|
if (errcode)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
do {
|
||||||
|
errcode = ext2fs_extent_get_info(handle, &info);
|
||||||
|
if (errcode)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is the first extent in an extent block that we
|
||||||
|
* haven't visited, rewrite the extent to force the ETB
|
||||||
|
* checksum to be rewritten.
|
||||||
|
*/
|
||||||
|
if (info.curr_entry == 1 && info.curr_level != 0 &&
|
||||||
|
!(extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)) {
|
||||||
|
errcode = ext2fs_extent_replace(handle, 0, &extent);
|
||||||
|
if (errcode)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip to the end of a block of leaf nodes */
|
||||||
|
if (extent.e_flags & EXT2_EXTENT_FLAGS_LEAF) {
|
||||||
|
errcode = ext2fs_extent_get(handle,
|
||||||
|
EXT2_EXTENT_LAST_SIB,
|
||||||
|
&extent);
|
||||||
|
if (errcode)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
errcode = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT, &extent);
|
||||||
|
} while (errcode == 0);
|
||||||
|
|
||||||
|
out:
|
||||||
|
/* Ok if we run off the end */
|
||||||
|
if (errcode == EXT2_ET_EXTENT_NO_NEXT)
|
||||||
|
errcode = 0;
|
||||||
|
ext2fs_extent_free(handle);
|
||||||
|
return errcode;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move inodes from the end of each block group inode table
|
* Move inodes from the end of each block group inode table
|
||||||
* so the tables can be shrinked
|
* so the tables can be shrinked
|
||||||
|
@ -262,6 +316,15 @@ errcode_t shrink_move_inodes(realloc_data *rd)
|
||||||
}
|
}
|
||||||
ext2fs_inode_alloc_stats2(rd->fs, new_ino, 1, inode->i_mode & S_IFDIR);
|
ext2fs_inode_alloc_stats2(rd->fs, new_ino, 1, inode->i_mode & S_IFDIR);
|
||||||
ext2fs_inode_alloc_stats2(rd->fs, ino, -1, inode->i_mode & S_IFDIR);
|
ext2fs_inode_alloc_stats2(rd->fs, ino, -1, inode->i_mode & S_IFDIR);
|
||||||
|
/* Rewrite extent block checksums with new inode number */
|
||||||
|
if (ext2fs_has_feature_metadata_csum(rd->fs->super) &&
|
||||||
|
(inode->i_flags & EXT4_EXTENTS_FL)) {
|
||||||
|
rd->fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
|
retval = rewrite_extents(rd->fs, new_ino);
|
||||||
|
rd->fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
|
if (retval)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
// Remember mapping
|
// Remember mapping
|
||||||
realloc_add_inode_map(rd, ino, new_ino);
|
realloc_add_inode_map(rd, ino, new_ino);
|
||||||
}
|
}
|
||||||
|
@ -330,6 +393,15 @@ static int change_inode_numbers_callback(ext2_ino_t dir, int entry,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fix_dirent_csum_callback(ext2_ino_t dir, int entry,
|
||||||
|
struct ext2_dir_entry *dirent, int offset,
|
||||||
|
int blocksize, char *buf, void *priv_data)
|
||||||
|
{
|
||||||
|
realloc_data *rd = priv_data;
|
||||||
|
ext2fs_dir_block_csum_set(rd->fs, dir, dirent);
|
||||||
|
return DIRENT_CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change inode numbers in all directory entries
|
* Change inode numbers in all directory entries
|
||||||
*/
|
*/
|
||||||
|
@ -347,6 +419,20 @@ errcode_t change_inode_numbers(realloc_data *rd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errcode_t fix_dirent_csums(realloc_data *rd)
|
||||||
|
{
|
||||||
|
ext2_ino_t ino;
|
||||||
|
realloc_sort_inode_map(rd);
|
||||||
|
for (ino = 1; ino <= rd->fs->super->s_inodes_count; ino++)
|
||||||
|
{
|
||||||
|
if (ext2fs_test_inode_bitmap2(rd->fs->inode_map, ino))
|
||||||
|
{
|
||||||
|
ext2fs_dir_iterate2(rd->fs, ino, 0, 0, fix_dirent_csum_callback, rd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1) Move inode tables
|
* 1) Move inode tables
|
||||||
* 2) Mark/unmark new/old inode table blocks
|
* 2) Mark/unmark new/old inode table blocks
|
||||||
|
@ -357,10 +443,11 @@ errcode_t change_super_and_bgd(realloc_data *rd)
|
||||||
blk64_t blk, end;
|
blk64_t blk, end;
|
||||||
dgrp_t grp, n_grp, flex_grp;
|
dgrp_t grp, n_grp, flex_grp;
|
||||||
__u32 used_ig, used_ibg, i, unus;
|
__u32 used_ig, used_ibg, i, unus;
|
||||||
|
ext2_ino_t inum;
|
||||||
errcode_t retval = 0;
|
errcode_t retval = 0;
|
||||||
int has_gdt_csum = EXT2_HAS_RO_COMPAT_FEATURE(rd->fs->super, EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
|
int has_gdt_csum = EXT2_HAS_RO_COMPAT_FEATURE(rd->fs->super, EXT4_FEATURE_RO_COMPAT_GDT_CSUM|EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
|
||||||
int cl = EXT2FS_CLUSTER_RATIO(rd->fs);
|
int cl = EXT2FS_CLUSTER_RATIO(rd->fs);
|
||||||
void *buf = NULL;
|
void *buf = NULL, *inode_buf = NULL;
|
||||||
ext2fs_flush(rd->fs);
|
ext2fs_flush(rd->fs);
|
||||||
retval = ext2fs_get_mem(EXT2_BLOCK_SIZE(rd->fs->super) * rd->ibg_new * rd->flexbg_size, &buf);
|
retval = ext2fs_get_mem(EXT2_BLOCK_SIZE(rd->fs->super) * rd->ibg_new * rd->flexbg_size, &buf);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
@ -427,15 +514,26 @@ errcode_t change_super_and_bgd(realloc_data *rd)
|
||||||
blk = ext2fs_inode_table_loc(rd->fs, grp);
|
blk = ext2fs_inode_table_loc(rd->fs, grp);
|
||||||
if (used_ibg > 0)
|
if (used_ibg > 0)
|
||||||
{
|
{
|
||||||
retval = io_channel_read_blk64(rd->fs->io, blk, min(used_ibg, rd->ibg_new),
|
inode_buf = buf + i*rd->ibg_new*EXT2_BLOCK_SIZE(rd->fs->super);
|
||||||
buf + i*rd->ibg_new*EXT2_BLOCK_SIZE(rd->fs->super));
|
retval = io_channel_read_blk64(rd->fs->io, blk, min(used_ibg, rd->ibg_new), inode_buf);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out;
|
goto out;
|
||||||
if (used_ig < rd->ig_new)
|
if (used_ig < rd->ig_new)
|
||||||
{
|
{
|
||||||
memset(buf + i*rd->ibg_new*EXT2_BLOCK_SIZE(rd->fs->super) +
|
memset(inode_buf + EXT2_INODE_SIZE(rd->fs->super) * used_ig,
|
||||||
EXT2_INODE_SIZE(rd->fs->super) * used_ig, 0,
|
0, EXT2_INODE_SIZE(rd->fs->super) * (rd->ig_new - used_ig));
|
||||||
EXT2_INODE_SIZE(rd->fs->super) * (rd->ig_new - used_ig));
|
}
|
||||||
|
if (ext2fs_has_feature_metadata_csum(rd->fs->super))
|
||||||
|
{
|
||||||
|
for (inum = 0; inum < used_ig || inum < rd->ig_new; inum++)
|
||||||
|
{
|
||||||
|
retval = ext2fs_inode_csum_set(
|
||||||
|
rd->fs, 1 + rd->ig_new*grp + inum,
|
||||||
|
inode_buf + EXT2_INODE_SIZE(rd->fs->super) * inum
|
||||||
|
);
|
||||||
|
if (retval)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -683,6 +781,12 @@ errcode_t do_realloc(realloc_data *rd)
|
||||||
{
|
{
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
/* printf("Phase %d: Fixing all directory checksums\n", phase++);
|
||||||
|
retval = fix_dirent_csums(rd);
|
||||||
|
if (retval)
|
||||||
|
{
|
||||||
|
goto out;
|
||||||
|
}*/
|
||||||
out:
|
out:
|
||||||
if (rd->new_itable_loc)
|
if (rd->new_itable_loc)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue