Bugfix:
authorgkostka <kostka.grzegorz@gmail.com>
Thu, 24 Oct 2013 00:18:52 +0000 (00:18 +0000)
committergkostka <kostka.grzegorz@gmail.com>
Thu, 24 Oct 2013 00:18:52 +0000 (00:18 +0000)
1. Directory hash MD4 bugfix.
2. A lot of fixes in directory indexing.
3. Improved inode allocation.

lwext4/ext4_dir_idx.c
lwext4/ext4_hash.c
lwext4/ext4_ialloc.c
lwext4/ext4_types.h

index 408d1eb74122ede80aaec40db242c4e4aae91266..4a75a353e55146f70ff675dbfae18a5831b69a2d 100644 (file)
@@ -351,7 +351,7 @@ static int ext4_dir_dx_get_leaf(struct ext4_hash_info *hinfo,
 \r
         uint16_t entry_space =\r
                 ext4_sb_get_block_size(&inode_ref->fs->sb) -\r
-                sizeof(struct ext4_directory_dx_dot_entry);\r
+                sizeof(struct ext4_fake_directory_entry);\r
 \r
         entry_space = entry_space / sizeof(struct ext4_directory_dx_entry);\r
 \r
@@ -606,7 +606,7 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
     void *entry_buffer_ptr = entry_buffer;\r
     while ((void *)dentry < (void *)(old_data_block->data + block_size)) {\r
         /* Read only valid entries */\r
-        if (ext4_dir_entry_ll_get_inode(dentry) != 0) {\r
+        if (ext4_dir_entry_ll_get_inode(dentry) && dentry->name_length) {\r
             uint8_t len = ext4_dir_entry_ll_get_name_length(\r
                     &inode_ref->fs->sb, dentry);\r
 \r
@@ -671,7 +671,7 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
     uint32_t mid = 0;\r
     uint32_t i;\r
     for ( i = 0; i < idx; ++i) {\r
-        if ((current_size + sort_array[i].rec_len) > (real_size / 2)) {\r
+        if ((current_size + sort_array[i].rec_len) > (block_size / 2)) {\r
             new_hash = sort_array[i].hash;\r
             mid = i;\r
             break;\r
@@ -747,9 +747,11 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
  */\r
 static int ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,\r
         struct  ext4_directory_dx_block *dx_blocks,\r
-        struct ext4_directory_dx_block *dx_block)\r
+        struct ext4_directory_dx_block *dx_block,\r
+        struct ext4_directory_dx_block **new_dx_block)\r
 {\r
     struct ext4_directory_dx_entry *entries;\r
+\r
     if (dx_block == dx_blocks)\r
         entries =\r
                 ((struct  ext4_directory_dx_root *) dx_block->block.data)->entries;\r
@@ -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;\r
         struct ext4_directory_dx_entry *new_entries = new_node->entries;\r
 \r
+        memset(&new_node->fake, 0, sizeof(struct ext4_fake_directory_entry));\r
+\r
         uint32_t block_size =\r
                 ext4_sb_get_block_size(&inode_ref->fs->sb);\r
 \r
+        new_node->fake.entry_length = block_size;\r
+\r
         /* Split leaf node */\r
         if (levels > 0) {\r
             uint32_t count_left = leaf_count / 2;\r
@@ -849,7 +855,10 @@ static int ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
 \r
             /* Finally insert new entry */\r
             ext4_dir_dx_insert_entry(dx_blocks, hash_right, new_iblock);\r
+            dx_blocks[0].block.dirty = true;\r
+            dx_blocks[1].block.dirty = true;\r
 \r
+            new_block.dirty = true;\r
             return ext4_block_set(inode_ref->fs->bdev, &new_block);\r
         } else {\r
             /* Create second level index */\r
@@ -879,9 +888,14 @@ static int ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
 \r
             /* Add new entry to the path */\r
             dx_block = dx_blocks + 1;\r
-            dx_block->position = dx_block->position - entries + new_entries;\r
+            dx_block->position = dx_blocks->position - entries + new_entries;\r
             dx_block->entries = new_entries;\r
             dx_block->block = new_block;\r
+\r
+            *new_dx_block = dx_block;\r
+\r
+            dx_blocks[0].block.dirty = true;\r
+            dx_blocks[1].block.dirty = true;\r
         }\r
     }\r
 \r
@@ -941,24 +955,26 @@ int       ext4_dir_dx_add_entry(struct ext4_inode_ref *parent,
     if (rc != EOK)\r
         goto release_index;\r
 \r
+    /*\r
+     * Check if there is needed to split index node\r
+     * (and recursively also parent nodes)\r
+     */\r
+    rc = ext4_dir_dx_split_index(parent, dx_blocks, dx_block, &dx_block);\r
+    if (rc != EOK)\r
+        goto release_target_index;\r
+\r
     struct ext4_block target_block;\r
     rc = ext4_block_get(fs->bdev, &target_block, leaf_block_addr);\r
     if (rc != EOK)\r
         goto release_index;\r
 \r
+\r
     /* Check if insert operation passed */\r
     rc = ext4_dir_try_insert_entry(&fs->sb, &target_block, child,\r
             name, name_len);\r
     if (rc == EOK)\r
         goto release_target_index;\r
 \r
-    /*\r
-     * Check if there is needed to split index node\r
-     * (and recursively also parent nodes)\r
-     */\r
-    rc = ext4_dir_dx_split_index(parent, dx_blocks, dx_block);\r
-    if (rc != EOK)\r
-        goto release_target_index;\r
 \r
     /* Split entries to two blocks (includes sorting by hash value) */\r
     struct ext4_block new_block;\r
index f3cdce5884d5336edac16d9051410b967fa3d257..9e7f8bbb16cc4df52c0aaa6ed40a2a338a991277 100644 (file)
@@ -292,8 +292,8 @@ ext2_htree_hash(const char *name, int len,
             len -= 32;\r
             name += 32;\r
         }\r
-        major = hash[0];\r
-        minor = hash[1];\r
+        major = hash[1];\r
+        minor = hash[2];\r
         break;\r
     default:\r
         goto error;\r
index 587373b70deda46a88b7b374842f57a3971d22aa..5d851718fa8d433aebf21f804f7e33228b401403 100644 (file)
@@ -137,13 +137,24 @@ int ext4_ialloc_alloc_inode(struct ext4_fs *fs, uint32_t *index, bool is_dir)
 {\r
     struct ext4_sblock *sb = &fs->sb;\r
 \r
-    uint32_t bgid = 0;\r
+    uint32_t bgid = fs->last_inode_bg_id;\r
     uint32_t bg_count = ext4_block_group_cnt(sb);\r
     uint32_t sb_free_inodes = ext4_get32(sb, free_inodes_count);\r
     uint32_t avg_free_inodes = sb_free_inodes / bg_count;\r
+    bool     rewind = false;\r
 \r
     /* Try to find free i-node in all block groups */\r
-    while (bgid < bg_count) {\r
+    while (bgid <= bg_count) {\r
+\r
+        if(bgid == bg_count){\r
+            if(rewind)\r
+                break;\r
+            bg_count = fs->last_inode_bg_id;\r
+            bgid = 0;\r
+            rewind = true;\r
+            continue;\r
+        }\r
+\r
         /* Load block group to check */\r
         struct ext4_block_group_ref bg_ref;\r
         int rc = ext4_fs_get_block_group_ref(fs, bgid, &bg_ref);\r
@@ -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;\r
 \r
         /* Read necessary values for algorithm */\r
-        uint32_t free_blocks = ext4_bg_get_free_blocks_count(bg, sb);\r
         uint32_t free_inodes = ext4_bg_get_free_inodes_count(bg, sb);\r
         uint32_t used_dirs = ext4_bg_get_used_dirs_count(bg, sb);\r
 \r
         /* Check if this block group is good candidate for allocation */\r
-        if ((free_inodes >= avg_free_inodes) && (free_blocks > 0)) {\r
+        if (free_inodes >= avg_free_inodes) {\r
             /* Load block with bitmap */\r
             uint32_t bitmap_block_addr = ext4_bg_get_inode_bitmap(\r
                     bg_ref.block_group, sb);\r
@@ -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,\r
                     index_in_group, bgid);\r
 \r
+            fs->last_inode_bg_id = bgid;\r
+\r
             return EOK;\r
         }\r
 \r
index ef1a42eeb5f84a7fea15bc411f0480f95901f384..8ce44da2aa806b3b1fdef054ea1c8140647d760e 100644 (file)
@@ -235,6 +235,8 @@ struct ext4_fs {
 
     uint64_t inode_block_limits[4];
     uint64_t inode_blocks_per_level[4];
+
+    uint32_t last_inode_bg_id;
 };