From 6cb0239e7eb67d939a299282e0ade7b37e7c0726 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Thu, 26 Dec 2013 13:00:03 +0000 Subject: [PATCH] adjust algorithm, add inode map impl based on reallocated "vector" --- realloc-inodes.c | 80 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 6 deletions(-) diff --git a/realloc-inodes.c b/realloc-inodes.c index 08c9987..69818c3 100644 --- a/realloc-inodes.c +++ b/realloc-inodes.c @@ -3,16 +3,22 @@ * * 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 + * 1.1) mark the end of each inode table as reserved (to make sure the inode allocator won't allocate it) + * 1.2) if there were some inodes, move them away: + * 1.2.1) allocate a new place for each inode, copy it there + * 1.2.2) remember the old->new inode number mapping + * 1.3) 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 + * 2.1) check all extra blocks that will be occupied by the growing inode tables, + * mark them as occupied if there are free () + * 2.2) move data away from 'extra blocks' that were 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) + * also translate old->new inode numbers remembered at (1.2.2) * 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) + * 6) If flex_bg is enabled, move parts of old inode tables so they are consecutive again * * 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 @@ -29,11 +35,73 @@ #include #include -#include "ext2fs/ext2_fs.h" -#include "ext2fs/ext2fs.h" +#include +#include #define _(a) (a) +typedef struct +{ + __u32 *inode_map, inode_map_size, inode_map_alloc; +} realloc_data; + +void add_inode_map(realloc_data *rd, __u32 old, __u32 new) +{ + if (!old || !new) + { + return; + } + if (2*rd->inode_map_size >= rd->inode_map_alloc) + { + rd->inode_map_alloc += 1024; + rd->inode_map = realloc(rd->inode_map, sizeof(__u32) * rd->inode_map_alloc); + } + rd->inode_map[rd->inode_map_size*2] = old; + rd->inode_map[rd->inode_map_size*2+1] = new; + rd->inode_map_size++; +} + +int compare_inode_map(const void *a, const void *b) +{ + return *((__u32*)a) - *((__u32*)b); +} + +void sort_inode_map(realloc_data *rd) +{ + if (!rd->inode_map) + { + return; + } + qsort(rd->inode_map, rd->inode_map_size, sizeof(__u32)*2, compare_inode_map); +} + +__u32 search_inode_map(realloc_data *rd, __u32 old) +{ + __u32 start = 0, end = rd->inode_map_size, cur, cur_old; + if (!rd->inode_map) + { + return 0; + } + while (end-start > 1) + { + cur = (start+end)>>1; + cur_old = rd->inode_map[cur<<1]; + if (cur < old) + { + start = cur+1; + } + else if (cur > old) + { + end = cur; + } + else + { + return rd->inode_map[(cur<<1)+1]; + } + } + return 0; +} + const char *program_name = "realloc-inodes"; int change_inode_numbers(ext2_ino_t dir, int entry,