An attempt to write a tool for ext4 that will allow to change inode count of a filesystem
commit
55f3fa2c01
|
@ -0,0 +1,3 @@
|
|||
all: realloc-inodes
|
||||
realloc-inodes: realloc-inodes.c
|
||||
gcc -o realloc-inodes -lcom_err -lext2fs realloc-inodes.c
|
|
@ -0,0 +1,122 @@
|
|||
/**
|
||||
* An attempt to write a tool for ext4 that will allow to change inode count of a filesystem.
|
||||
*
|
||||
* In theory it shouldn't be that hard:
|
||||
* 1) If shrinking:
|
||||
* 1.1) move inodes so that the end of inode table is empty
|
||||
* 1.2) mark some blocks that belonged to inode table as free
|
||||
* 2) If growing:
|
||||
* 2.1) move data blocks so there is enough space reserved for new inode table
|
||||
* 2.2) mark some blocks that should belong to inode table as occupied
|
||||
* 3) Change all inode numbers in directory entries so that
|
||||
* new_num = (old_num/old_inodes_per_group)*new_inodes_per_group + (old_num%inodes_per_group)
|
||||
* 4) Change superblock: s_inodes_count, s_free_inodes_count, s_inodes_per_group
|
||||
* 5) Change block group descriptors: bg_inode_table_(lo,hi), bg_free_inodes_count_(lo,hi),
|
||||
* bg_inode_bitmap_csum_(lo,hi), bg_itable_unused_(lo,hi)
|
||||
*
|
||||
* This is a destructive process involving metadata change so it would be good if
|
||||
* we could first write a file containing all necessary changes, then backup all
|
||||
* changed blocks, and then write new blocks to the disk. (maybe just use undo_io_manager?)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "ext2fs/ext2_fs.h"
|
||||
#include "ext2fs/ext2fs.h"
|
||||
|
||||
#define _(a) (a)
|
||||
|
||||
const char *program_name = "realloc-inodes";
|
||||
|
||||
// try to read out all directory inodes?
|
||||
void test(ext2_filsys fs)
|
||||
{
|
||||
int i, j, retval;
|
||||
blk64_t blk;
|
||||
void *buf;
|
||||
struct ext2_inode *inode;
|
||||
retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group, &buf);
|
||||
for (i = 0; i < fs->group_desc_count; i++)
|
||||
{
|
||||
// read inode table of a group
|
||||
blk = ext2fs_inode_table_loc(fs, i);
|
||||
retval = io_channel_read_blk64(fs->io, blk, fs->inode_blocks_per_group, buf);
|
||||
if (retval)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
for (j = 0; j < fs->super->s_inodes_per_group; j++)
|
||||
{
|
||||
inode = (struct ext2_inode*)(buf + EXT2_INODE_SIZE(fs->super) * j);
|
||||
if (inode->i_mode & S_IFDIR)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
errout:
|
||||
ext2fs_free_mem(&buf);
|
||||
}
|
||||
|
||||
int main(int narg, char **args)
|
||||
{
|
||||
ext2_filsys fs;
|
||||
io_manager io_ptr = unix_io_manager;
|
||||
int optind, fd, retval, io_flags = 0, force = 0;
|
||||
ext2fs_struct_stat st_buf;
|
||||
char *device_name, *io_options;
|
||||
|
||||
optind = 1;
|
||||
device_name = args[optind++];
|
||||
add_error_table(&et_ext2_error_table);
|
||||
fd = ext2fs_open_file(device_name, O_RDWR, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
com_err("open", errno, _("while opening %s"), device_name);
|
||||
exit(1);
|
||||
}
|
||||
retval = ext2fs_fstat(fd, &st_buf);
|
||||
if (retval < 0)
|
||||
{
|
||||
com_err("open", errno, _("while getting stat information for %s"), device_name);
|
||||
exit(1);
|
||||
}
|
||||
if (!S_ISREG(st_buf.st_mode))
|
||||
{
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
io_options = strchr(device_name, '?');
|
||||
if (io_options)
|
||||
{
|
||||
*io_options++ = 0;
|
||||
}
|
||||
//io_flags = EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE;
|
||||
io_flags |= EXT2_FLAG_64BITS;
|
||||
retval = ext2fs_open2(device_name, io_options, io_flags, 0, 0, io_ptr, &fs);
|
||||
if (retval)
|
||||
{
|
||||
com_err(program_name, retval, _("while trying to open %s"), device_name);
|
||||
printf(_("Couldn't find valid filesystem superblock.\n"));
|
||||
exit(1);
|
||||
}
|
||||
if (!force && ((fs->super->s_state & EXT2_ERROR_FS) || ((fs->super->s_state & EXT2_VALID_FS) == 0)))
|
||||
{
|
||||
fprintf(stderr, _("Please run 'e2fsck -f %s' first.\n\n"), device_name);
|
||||
exit(1);
|
||||
}
|
||||
test(fs);
|
||||
ext2fs_close(fs);
|
||||
if (fd > 0)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue