Roughly implemented inode table moving
parent
bf357faaf4
commit
f58ece6d8c
178
realloc-inodes.c
178
realloc-inodes.c
|
@ -117,10 +117,16 @@ ext2_ino_t realloc_search_inode_map(realloc_data *rd, ext2_ino_t old)
|
|||
*/
|
||||
int shrink_move_inodes(realloc_data *rd)
|
||||
{
|
||||
int retval;
|
||||
int retval = 0, inode_size = EXT2_INODE_SIZE(rd->fs->super);
|
||||
__u32 group, i, last = rd->inode_map_size;
|
||||
__u32 new_group;
|
||||
ext2_ino_t ino, new_ino;
|
||||
struct ext2_inode *inode = NULL;
|
||||
retval = ext2fs_get_mem(inode_size, &inode);
|
||||
if (retval)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
for (group = 0; group < rd->fs->group_desc_count; group++)
|
||||
{
|
||||
for (i = rd->new_inodes_per_group; i < rd->fs->super->s_inodes_per_group; i++)
|
||||
|
@ -143,32 +149,49 @@ int shrink_move_inodes(realloc_data *rd)
|
|||
} while (new_group != group);
|
||||
if (retval)
|
||||
{
|
||||
return ENOENT;
|
||||
// No space to move this inode
|
||||
goto out;
|
||||
}
|
||||
// Copy inode to the new place
|
||||
retval = ext2fs_read_inode_full(rd->fs, ino, inode, inode_size);
|
||||
if (retval)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
retval = ext2fs_write_inode_full(rd->fs, new_ino, inode, inode_size);
|
||||
if (retval)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
retval = ext2fs_mark_inode_bitmap2(rd->fs->inode_map, new_ino);
|
||||
if (retval)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
// Remember mapping
|
||||
realloc_add_inode_map(rd, ino, new_ino);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Move inodes
|
||||
for (i = last; i < rd->inode_map_size; i++)
|
||||
out:
|
||||
if (inode)
|
||||
{
|
||||
ino = rd->inode_map[i<<1];
|
||||
|
||||
ext2fs_free_mem(&inode);
|
||||
}
|
||||
return 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move blocks from after the end of each block group inode table
|
||||
* Move data blocks from after the end of each block group inode table
|
||||
* so the tables can be grown
|
||||
*/
|
||||
int extend_move_blocks(realloc_data *rd)
|
||||
{
|
||||
|
||||
return 0;
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
int change_inode_numbers_callback(ext2_ino_t dir, int entry,
|
||||
static int change_inode_numbers_callback(ext2_ino_t dir, int entry,
|
||||
struct ext2_dir_entry *dirent, int offset,
|
||||
int blocksize, char *buf, void *priv_data)
|
||||
{
|
||||
|
@ -184,6 +207,11 @@ int change_inode_numbers_callback(ext2_ino_t dir, int entry,
|
|||
strncpy(name, dirent->name, dirent->name_len & 0xff);
|
||||
name[dirent->name_len & 0xff] = 0;
|
||||
printf("%s: old %d, new %d\n", name, dirent->inode, new_ino);
|
||||
if (new_ino != dirent->inode)
|
||||
{
|
||||
dirent->inode = new_ino;
|
||||
return DIRENT_CHANGED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -192,29 +220,33 @@ int change_inode_numbers_callback(ext2_ino_t dir, int entry,
|
|||
*/
|
||||
int change_inode_numbers(realloc_data *rd)
|
||||
{
|
||||
int i, j, retval;
|
||||
int j, retval;
|
||||
dgrp_t grp;
|
||||
blk64_t blk;
|
||||
void *buf;
|
||||
struct ext2_inode *inode;
|
||||
retval = ext2fs_get_mem(rd->fs->blocksize * rd->fs->inode_blocks_per_group, &buf);
|
||||
retval = ext2fs_get_mem(EXT2_BLOCK_SIZE(rd->fs->super) * rd->fs->inode_blocks_per_group, &buf);
|
||||
realloc_sort_inode_map(rd);
|
||||
for (i = 0; i < rd->fs->group_desc_count; i++)
|
||||
for (grp = 0; grp < rd->fs->group_desc_count; grp++)
|
||||
{
|
||||
// read inode table of a group
|
||||
blk = ext2fs_inode_table_loc(rd->fs, i);
|
||||
retval = io_channel_read_blk64(rd->fs->io, blk, rd->fs->inode_blocks_per_group, buf);
|
||||
if (retval)
|
||||
if (!ext2fs_bg_flags_test(rd->fs, grp, EXT2_BG_INODE_UNINIT))
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (j = 0; j < rd->fs->super->s_inodes_per_group; j++)
|
||||
{
|
||||
inode = (struct ext2_inode*)(buf + EXT2_INODE_SIZE(rd->fs->super) * j);
|
||||
if (inode->i_mode & S_IFDIR)
|
||||
blk = ext2fs_inode_table_loc(rd->fs, grp);
|
||||
retval = io_channel_read_blk64(rd->fs->io, blk, rd->fs->inode_blocks_per_group, buf);
|
||||
if (retval)
|
||||
{
|
||||
printf("Directory %d\n", 1+j+i*rd->fs->super->s_inodes_per_group);
|
||||
ext2fs_dir_iterate2(rd->fs, 1+j+i*rd->fs->super->s_inodes_per_group, 0, 0, change_inode_numbers_callback, rd);
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
for (j = 0; j < rd->fs->super->s_inodes_per_group; j++)
|
||||
{
|
||||
inode = (struct ext2_inode*)(buf + EXT2_INODE_SIZE(rd->fs->super) * j);
|
||||
if (inode->i_mode & S_IFDIR)
|
||||
{
|
||||
printf("Directory %d\n", 1+j+grp*rd->fs->super->s_inodes_per_group);
|
||||
ext2fs_dir_iterate2(rd->fs, 1+j+grp*rd->fs->super->s_inodes_per_group, 0, 0, change_inode_numbers_callback, rd);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -224,7 +256,96 @@ int change_inode_numbers(realloc_data *rd)
|
|||
|
||||
/**
|
||||
* If flex_bg is enabled, move inode tables so they are consecutive again
|
||||
* Then adjust superblock and block group descriptors
|
||||
*/
|
||||
int flex_bg_move_itables(realloc_data *rd)
|
||||
{
|
||||
blk64_t it_start, blk;
|
||||
dgrp_t grp, n_flex, last_grp;
|
||||
int flexbg_size = 0, i, retval = 0;
|
||||
void *buf = NULL;
|
||||
ext2fs_flush(rd->fs);
|
||||
if (rd->new_inode_blocks_per_group != rd->fs->inode_blocks_per_group)
|
||||
{
|
||||
// Move inode tables, if flex_bg is active
|
||||
if (EXT2_HAS_INCOMPAT_FEATURE(rd->fs->super, EXT4_FEATURE_INCOMPAT_FLEX_BG)
|
||||
&& rd->fs->super->s_log_groups_per_flex)
|
||||
{
|
||||
flexbg_size = 1 << rd->fs->super->s_log_groups_per_flex;
|
||||
retval = ext2fs_get_mem(EXT2_BLOCK_SIZE(rd->fs->super) * rd->new_inode_blocks_per_group * flexbg_size, &buf);
|
||||
if (retval)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
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)
|
||||
{
|
||||
last_grp = rd->fs->group_desc_count;
|
||||
}
|
||||
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))
|
||||
{
|
||||
blk = ext2fs_inode_table_loc(rd->fs, grp);
|
||||
retval = io_channel_read_blk64(rd->fs->io, blk, rd->new_inode_blocks_per_group,
|
||||
buf + i*rd->new_inode_blocks_per_group*EXT2_BLOCK_SIZE(rd->fs->super));
|
||||
if (retval)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
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);
|
||||
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_range(rd->fs->block_map, it_start+blk, (rd->fs->inode_blocks_per_group-rd->new_inode_blocks_per_group)*flexbg_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ext2fs_mark_block_bitmap_range(rd->fs->block_map, it_start+blk, (rd->new_inode_blocks_per_group-rd->fs->inode_blocks_per_group)*flexbg_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
ext2fs_unmark_block_bitmap_range(rd->fs->block_map, it_start, rd->fs->inode_blocks_per_group-rd->new_inode_blocks_per_group);
|
||||
}
|
||||
else
|
||||
{
|
||||
ext2fs_mark_block_bitmap_range(rd->fs->block_map, it_start, rd->new_inode_blocks_per_group-rd->fs->inode_blocks_per_group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (buf)
|
||||
{
|
||||
ext2fs_free_mem(&buf);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust superblock and block group descriptors
|
||||
*/
|
||||
int change_super_and_bgd(realloc_data *rd)
|
||||
{
|
||||
|
@ -288,6 +409,11 @@ int do_realloc(realloc_data *rd)
|
|||
{
|
||||
return retval;
|
||||
}
|
||||
retval = flex_bg_move_itables(rd);
|
||||
if (retval)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
retval = change_super_and_bgd(rd);
|
||||
if (retval)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue