Browse Source

Bugfix:

1. Directory hash MD4 bugfix.
2. A lot of fixes in directory indexing.
3. Improved inode allocation.
pull/1/head
gkostka 11 years ago
parent
commit
4bd842820e
  1. 40
      lwext4/ext4_dir_idx.c
  2. 4
      lwext4/ext4_hash.c
  3. 20
      lwext4/ext4_ialloc.c
  4. 2
      lwext4/ext4_types.h

40
lwext4/ext4_dir_idx.c

@ -351,7 +351,7 @@ static int ext4_dir_dx_get_leaf(struct ext4_hash_info *hinfo,
uint16_t entry_space = uint16_t entry_space =
ext4_sb_get_block_size(&inode_ref->fs->sb) - ext4_sb_get_block_size(&inode_ref->fs->sb) -
sizeof(struct ext4_directory_dx_dot_entry); sizeof(struct ext4_fake_directory_entry);
entry_space = entry_space / sizeof(struct ext4_directory_dx_entry); entry_space = entry_space / sizeof(struct ext4_directory_dx_entry);
@ -606,7 +606,7 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
void *entry_buffer_ptr = entry_buffer; void *entry_buffer_ptr = entry_buffer;
while ((void *)dentry < (void *)(old_data_block->data + block_size)) { while ((void *)dentry < (void *)(old_data_block->data + block_size)) {
/* Read only valid entries */ /* Read only valid entries */
if (ext4_dir_entry_ll_get_inode(dentry) != 0) { if (ext4_dir_entry_ll_get_inode(dentry) && dentry->name_length) {
uint8_t len = ext4_dir_entry_ll_get_name_length( uint8_t len = ext4_dir_entry_ll_get_name_length(
&inode_ref->fs->sb, dentry); &inode_ref->fs->sb, dentry);
@ -671,7 +671,7 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
uint32_t mid = 0; uint32_t mid = 0;
uint32_t i; uint32_t i;
for ( i = 0; i < idx; ++i) { for ( i = 0; i < idx; ++i) {
if ((current_size + sort_array[i].rec_len) > (real_size / 2)) { if ((current_size + sort_array[i].rec_len) > (block_size / 2)) {
new_hash = sort_array[i].hash; new_hash = sort_array[i].hash;
mid = i; mid = i;
break; break;
@ -747,9 +747,11 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
*/ */
static int ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref, static int ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
struct ext4_directory_dx_block *dx_blocks, struct ext4_directory_dx_block *dx_blocks,
struct ext4_directory_dx_block *dx_block) struct ext4_directory_dx_block *dx_block,
struct ext4_directory_dx_block **new_dx_block)
{ {
struct ext4_directory_dx_entry *entries; struct ext4_directory_dx_entry *entries;
if (dx_block == dx_blocks) if (dx_block == dx_blocks)
entries = entries =
((struct ext4_directory_dx_root *) dx_block->block.data)->entries; ((struct ext4_directory_dx_root *) dx_block->block.data)->entries;
@ -801,9 +803,13 @@ static int ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
struct ext4_directory_dx_node *new_node = (void *)new_block.data; struct ext4_directory_dx_node *new_node = (void *)new_block.data;
struct ext4_directory_dx_entry *new_entries = new_node->entries; struct ext4_directory_dx_entry *new_entries = new_node->entries;
memset(&new_node->fake, 0, sizeof(struct ext4_fake_directory_entry));
uint32_t block_size = uint32_t block_size =
ext4_sb_get_block_size(&inode_ref->fs->sb); ext4_sb_get_block_size(&inode_ref->fs->sb);
new_node->fake.entry_length = block_size;
/* Split leaf node */ /* Split leaf node */
if (levels > 0) { if (levels > 0) {
uint32_t count_left = leaf_count / 2; uint32_t count_left = leaf_count / 2;
@ -849,7 +855,10 @@ static int ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
/* Finally insert new entry */ /* Finally insert new entry */
ext4_dir_dx_insert_entry(dx_blocks, hash_right, new_iblock); ext4_dir_dx_insert_entry(dx_blocks, hash_right, new_iblock);
dx_blocks[0].block.dirty = true;
dx_blocks[1].block.dirty = true;
new_block.dirty = true;
return ext4_block_set(inode_ref->fs->bdev, &new_block); return ext4_block_set(inode_ref->fs->bdev, &new_block);
} else { } else {
/* Create second level index */ /* Create second level index */
@ -879,9 +888,14 @@ static int ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
/* Add new entry to the path */ /* Add new entry to the path */
dx_block = dx_blocks + 1; dx_block = dx_blocks + 1;
dx_block->position = dx_block->position - entries + new_entries; dx_block->position = dx_blocks->position - entries + new_entries;
dx_block->entries = new_entries; dx_block->entries = new_entries;
dx_block->block = new_block; dx_block->block = new_block;
*new_dx_block = dx_block;
dx_blocks[0].block.dirty = true;
dx_blocks[1].block.dirty = true;
} }
} }
@ -941,24 +955,26 @@ int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent,
if (rc != EOK) if (rc != EOK)
goto release_index; goto release_index;
/*
* Check if there is needed to split index node
* (and recursively also parent nodes)
*/
rc = ext4_dir_dx_split_index(parent, dx_blocks, dx_block, &dx_block);
if (rc != EOK)
goto release_target_index;
struct ext4_block target_block; struct ext4_block target_block;
rc = ext4_block_get(fs->bdev, &target_block, leaf_block_addr); rc = ext4_block_get(fs->bdev, &target_block, leaf_block_addr);
if (rc != EOK) if (rc != EOK)
goto release_index; goto release_index;
/* Check if insert operation passed */ /* Check if insert operation passed */
rc = ext4_dir_try_insert_entry(&fs->sb, &target_block, child, rc = ext4_dir_try_insert_entry(&fs->sb, &target_block, child,
name, name_len); name, name_len);
if (rc == EOK) if (rc == EOK)
goto release_target_index; goto release_target_index;
/*
* Check if there is needed to split index node
* (and recursively also parent nodes)
*/
rc = ext4_dir_dx_split_index(parent, dx_blocks, dx_block);
if (rc != EOK)
goto release_target_index;
/* Split entries to two blocks (includes sorting by hash value) */ /* Split entries to two blocks (includes sorting by hash value) */
struct ext4_block new_block; struct ext4_block new_block;

4
lwext4/ext4_hash.c

@ -292,8 +292,8 @@ ext2_htree_hash(const char *name, int len,
len -= 32; len -= 32;
name += 32; name += 32;
} }
major = hash[0]; major = hash[1];
minor = hash[1]; minor = hash[2];
break; break;
default: default:
goto error; goto error;

20
lwext4/ext4_ialloc.c

@ -137,13 +137,24 @@ int ext4_ialloc_alloc_inode(struct ext4_fs *fs, uint32_t *index, bool is_dir)
{ {
struct ext4_sblock *sb = &fs->sb; struct ext4_sblock *sb = &fs->sb;
uint32_t bgid = 0; uint32_t bgid = fs->last_inode_bg_id;
uint32_t bg_count = ext4_block_group_cnt(sb); uint32_t bg_count = ext4_block_group_cnt(sb);
uint32_t sb_free_inodes = ext4_get32(sb, free_inodes_count); uint32_t sb_free_inodes = ext4_get32(sb, free_inodes_count);
uint32_t avg_free_inodes = sb_free_inodes / bg_count; uint32_t avg_free_inodes = sb_free_inodes / bg_count;
bool rewind = false;
/* Try to find free i-node in all block groups */ /* Try to find free i-node in all block groups */
while (bgid < bg_count) { while (bgid <= bg_count) {
if(bgid == bg_count){
if(rewind)
break;
bg_count = fs->last_inode_bg_id;
bgid = 0;
rewind = true;
continue;
}
/* Load block group to check */ /* Load block group to check */
struct ext4_block_group_ref bg_ref; struct ext4_block_group_ref bg_ref;
int rc = ext4_fs_get_block_group_ref(fs, bgid, &bg_ref); int rc = ext4_fs_get_block_group_ref(fs, bgid, &bg_ref);
@ -153,12 +164,11 @@ int ext4_ialloc_alloc_inode(struct ext4_fs *fs, uint32_t *index, bool is_dir)
struct ext4_bgroup *bg = bg_ref.block_group; struct ext4_bgroup *bg = bg_ref.block_group;
/* Read necessary values for algorithm */ /* Read necessary values for algorithm */
uint32_t free_blocks = ext4_bg_get_free_blocks_count(bg, sb);
uint32_t free_inodes = ext4_bg_get_free_inodes_count(bg, sb); uint32_t free_inodes = ext4_bg_get_free_inodes_count(bg, sb);
uint32_t used_dirs = ext4_bg_get_used_dirs_count(bg, sb); uint32_t used_dirs = ext4_bg_get_used_dirs_count(bg, sb);
/* Check if this block group is good candidate for allocation */ /* Check if this block group is good candidate for allocation */
if ((free_inodes >= avg_free_inodes) && (free_blocks > 0)) { if (free_inodes >= avg_free_inodes) {
/* Load block with bitmap */ /* Load block with bitmap */
uint32_t bitmap_block_addr = ext4_bg_get_inode_bitmap( uint32_t bitmap_block_addr = ext4_bg_get_inode_bitmap(
bg_ref.block_group, sb); bg_ref.block_group, sb);
@ -233,6 +243,8 @@ int ext4_ialloc_alloc_inode(struct ext4_fs *fs, uint32_t *index, bool is_dir)
*index = ext4_ialloc_index_in_group2inode(sb, *index = ext4_ialloc_index_in_group2inode(sb,
index_in_group, bgid); index_in_group, bgid);
fs->last_inode_bg_id = bgid;
return EOK; return EOK;
} }

2
lwext4/ext4_types.h

@ -235,6 +235,8 @@ struct ext4_fs {
uint64_t inode_block_limits[4]; uint64_t inode_block_limits[4];
uint64_t inode_blocks_per_level[4]; uint64_t inode_blocks_per_level[4];
uint32_t last_inode_bg_id;
}; };

Loading…
Cancel
Save