shithub: lwext4

Download patch

ref: 4bd842820e2740c23908932e264cbf43cb1fdd27
parent: ffb796f2aa4c7933dbce539865d90e7db00fabf4
author: gkostka <kostka.grzegorz@gmail.com>
date: Wed Oct 23 20:18:52 EDT 2013

Bugfix:
1. Directory hash MD4 bugfix.
2. A lot of fixes in directory indexing.
3. Improved inode allocation.

--- a/lwext4/ext4_dir_idx.c
+++ b/lwext4/ext4_dir_idx.c
@@ -351,7 +351,7 @@
 
         uint16_t entry_space =
                 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);
 
@@ -606,7 +606,7 @@
     void *entry_buffer_ptr = entry_buffer;
     while ((void *)dentry < (void *)(old_data_block->data + block_size)) {
         /* 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(
                     &inode_ref->fs->sb, dentry);
 
@@ -671,7 +671,7 @@
     uint32_t mid = 0;
     uint32_t 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;
             mid = i;
             break;
@@ -747,9 +747,11 @@
  */
 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_block)
+        struct ext4_directory_dx_block *dx_block,
+        struct ext4_directory_dx_block **new_dx_block)
 {
     struct ext4_directory_dx_entry *entries;
+
     if (dx_block == dx_blocks)
         entries =
                 ((struct  ext4_directory_dx_root *) dx_block->block.data)->entries;
@@ -801,9 +803,13 @@
         struct ext4_directory_dx_node  *new_node 	= (void *)new_block.data;
         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 =
                 ext4_sb_get_block_size(&inode_ref->fs->sb);
 
+        new_node->fake.entry_length = block_size;
+
         /* Split leaf node */
         if (levels > 0) {
             uint32_t count_left = leaf_count / 2;
@@ -849,7 +855,10 @@
 
             /* Finally insert new entry */
             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);
         } else {
             /* Create second level index */
@@ -879,9 +888,14 @@
 
             /* Add new entry to the path */
             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->block = new_block;
+
+            *new_dx_block = dx_block;
+
+            dx_blocks[0].block.dirty = true;
+            dx_blocks[1].block.dirty = true;
         }
     }
 
@@ -941,11 +955,20 @@
     if (rc != EOK)
         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;
     rc = ext4_block_get(fs->bdev, &target_block, leaf_block_addr);
     if (rc != EOK)
         goto release_index;
 
+
     /* Check if insert operation passed */
     rc = ext4_dir_try_insert_entry(&fs->sb, &target_block, child,
             name, name_len);
@@ -952,13 +975,6 @@
     if (rc == EOK)
         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) */
     struct ext4_block new_block;
--- a/lwext4/ext4_hash.c
+++ b/lwext4/ext4_hash.c
@@ -292,8 +292,8 @@
             len -= 32;
             name += 32;
         }
-        major = hash[0];
-        minor = hash[1];
+        major = hash[1];
+        minor = hash[2];
         break;
     default:
         goto error;
--- a/lwext4/ext4_ialloc.c
+++ b/lwext4/ext4_ialloc.c
@@ -137,13 +137,24 @@
 {
     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 sb_free_inodes = ext4_get32(sb, free_inodes_count);
     uint32_t avg_free_inodes = sb_free_inodes / bg_count;
+    bool     rewind = false;
 
     /* 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 */
         struct ext4_block_group_ref bg_ref;
         int rc = ext4_fs_get_block_group_ref(fs, bgid, &bg_ref);
@@ -153,12 +164,11 @@
         struct ext4_bgroup *bg = bg_ref.block_group;
 
         /* 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 used_dirs = ext4_bg_get_used_dirs_count(bg, sb);
 
         /* 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 */
             uint32_t bitmap_block_addr = ext4_bg_get_inode_bitmap(
                     bg_ref.block_group, sb);
@@ -232,6 +242,8 @@
             /* Compute the absolute i-nodex number */
             *index = ext4_ialloc_index_in_group2inode(sb,
                     index_in_group, bgid);
+
+            fs->last_inode_bg_id = bgid;
 
             return EOK;
         }
--- a/lwext4/ext4_types.h
+++ b/lwext4/ext4_types.h
@@ -235,6 +235,8 @@
 
     uint64_t inode_block_limits[4];
     uint64_t inode_blocks_per_level[4];
+
+    uint32_t last_inode_bg_id;
 };