Mkfs works for ext2/ext3 features
[lwext4.git] / lwext4 / ext4_dir_idx.c
index a34fc50c8b58ed16932f0165df84b017b1ee9084..df1d999d06459daa5fd7b26ff3f4e89e296e1e5b 100644 (file)
@@ -40,6 +40,8 @@
 #include "ext4_blockdev.h"
 #include "ext4_fs.h"
 #include "ext4_super.h"
+#include "ext4_inode.h"
+#include "ext4_crc32c.h"
 #include "ext4_hash.h"
 
 #include <string.h>
@@ -50,7 +52,7 @@
  * @return Hash algorithm version
  */
 static inline uint8_t ext4_dir_dx_root_info_get_hash_version(
-    struct ext4_directory_dx_root_info *root_info)
+    struct ext4_dir_idx_root_info *root_info)
 {
        return root_info->hash_version;
 }
@@ -60,7 +62,7 @@ static inline uint8_t ext4_dir_dx_root_info_get_hash_version(
  * @param v Hash algorithm version
  */
 static inline void ext4_dir_dx_root_info_set_hash_version(
-    struct ext4_directory_dx_root_info *root_info, uint8_t v)
+    struct ext4_dir_idx_root_info *root_info, uint8_t v)
 {
        root_info->hash_version = v;
 }
@@ -70,7 +72,7 @@ static inline void ext4_dir_dx_root_info_set_hash_version(
  * @return Length of the structure
  */
 static inline uint8_t ext4_dir_dx_root_info_get_info_length(
-    struct ext4_directory_dx_root_info *root_info)
+    struct ext4_dir_idx_root_info *root_info)
 {
        return root_info->info_length;
 }
@@ -80,7 +82,7 @@ static inline uint8_t ext4_dir_dx_root_info_get_info_length(
  * @param info_length Length of the structure
  */
 static inline void ext4_dir_dx_root_info_set_info_length(
-    struct ext4_directory_dx_root_info *root_info, uint8_t len)
+    struct ext4_dir_idx_root_info *root_info, uint8_t len)
 {
        root_info->info_length = len;
 }
@@ -90,7 +92,7 @@ static inline void ext4_dir_dx_root_info_set_info_length(
  * @return Height of HTree (actually only 0 or 1)
  */
 static inline uint8_t ext4_dir_dx_root_info_get_indirect_levels(
-    struct ext4_directory_dx_root_info *root_info)
+    struct ext4_dir_idx_root_info *root_info)
 {
        return root_info->indirect_levels;
 }
@@ -100,7 +102,7 @@ static inline uint8_t ext4_dir_dx_root_info_get_indirect_levels(
  * @param lvl Height of HTree (actually only 0 or 1)
  */
 static inline void ext4_dir_dx_root_info_set_indirect_levels(
-    struct ext4_directory_dx_root_info *root_info, uint8_t lvl)
+    struct ext4_dir_idx_root_info *root_info, uint8_t lvl)
 {
        root_info->indirect_levels = lvl;
 }
@@ -110,7 +112,7 @@ static inline void ext4_dir_dx_root_info_set_indirect_levels(
  * @return Maximum of entries in node
  */
 static inline uint16_t
-ext4_dir_dx_countlimit_get_limit(struct ext4_directory_dx_countlimit *climit)
+ext4_dir_dx_countlimit_get_limit(struct ext4_dir_idx_countlimit *climit)
 {
        return to_le16(climit->limit);
 }
@@ -120,7 +122,7 @@ ext4_dir_dx_countlimit_get_limit(struct ext4_directory_dx_countlimit *climit)
  * @param limit Maximum of entries in node
  */
 static inline void
-ext4_dir_dx_countlimit_set_limit(struct ext4_directory_dx_countlimit *climit,
+ext4_dir_dx_countlimit_set_limit(struct ext4_dir_idx_countlimit *climit,
                                 uint16_t limit)
 {
        climit->limit = to_le16(limit);
@@ -131,7 +133,7 @@ ext4_dir_dx_countlimit_set_limit(struct ext4_directory_dx_countlimit *climit,
  * @return Number of entries in node
  */
 static inline uint16_t
-ext4_dir_dx_countlimit_get_count(struct ext4_directory_dx_countlimit *climit)
+ext4_dir_dx_countlimit_get_count(struct ext4_dir_idx_countlimit *climit)
 {
        return to_le16(climit->count);
 }
@@ -141,7 +143,7 @@ ext4_dir_dx_countlimit_get_count(struct ext4_directory_dx_countlimit *climit)
  * @param count Number of entries in node
  */
 static inline void
-ext4_dir_dx_countlimit_set_count(struct ext4_directory_dx_countlimit *climit,
+ext4_dir_dx_countlimit_set_count(struct ext4_dir_idx_countlimit *climit,
                                 uint16_t count)
 {
        climit->count = to_le16(count);
@@ -152,7 +154,7 @@ ext4_dir_dx_countlimit_set_count(struct ext4_directory_dx_countlimit *climit,
  * @return Hash value
  */
 static inline uint32_t
-ext4_dir_dx_entry_get_hash(struct ext4_directory_dx_entry *entry)
+ext4_dir_dx_entry_get_hash(struct ext4_dir_idx_entry *entry)
 {
        return to_le32(entry->hash);
 }
@@ -162,7 +164,7 @@ ext4_dir_dx_entry_get_hash(struct ext4_directory_dx_entry *entry)
  * @param hash  Hash value
  */
 static inline void
-ext4_dir_dx_entry_set_hash(struct ext4_directory_dx_entry *entry, uint32_t hash)
+ext4_dir_dx_entry_set_hash(struct ext4_dir_idx_entry *entry, uint32_t hash)
 {
        entry->hash = to_le32(hash);
 }
@@ -172,7 +174,7 @@ ext4_dir_dx_entry_set_hash(struct ext4_directory_dx_entry *entry, uint32_t hash)
  * @return Block address of child node
  */
 static inline uint32_t
-ext4_dir_dx_entry_get_block(struct ext4_directory_dx_entry *entry)
+ext4_dir_dx_entry_get_block(struct ext4_dir_idx_entry *entry)
 {
        return to_le32(entry->block);
 }
@@ -182,7 +184,7 @@ ext4_dir_dx_entry_get_block(struct ext4_directory_dx_entry *entry)
  * @param block Block address of child node
  */
 static inline void
-ext4_dir_dx_entry_set_block(struct ext4_directory_dx_entry *entry,
+ext4_dir_dx_entry_set_block(struct ext4_dir_idx_entry *entry,
                            uint32_t block)
 {
        entry->block = to_le32(block);
@@ -202,24 +204,185 @@ static int ext4_dir_dx_hash_string(struct ext4_hash_info *hinfo, int len,
                               &hinfo->hash, &hinfo->minor_hash);
 }
 
+#if CONFIG_META_CSUM_ENABLE
+static uint32_t
+ext4_dir_dx_checksum(struct ext4_inode_ref *inode_ref,
+                void *dirent,
+                int count_offset, int count, struct ext4_dir_idx_tail *t)
+{
+       uint32_t orig_checksum, checksum = 0;
+       struct ext4_sblock *sb = &inode_ref->fs->sb;
+       int size;
+
+       /* Compute the checksum only if the filesystem supports it */
+       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) {
+               uint32_t ino_index = to_le32(inode_ref->index);
+               uint32_t ino_gen =
+                       to_le32(ext4_inode_get_generation(inode_ref->inode));
+
+               size = count_offset +
+                       (count * sizeof(struct ext4_dir_idx_tail));
+               orig_checksum = t->checksum;
+               t->checksum = 0;
+               /* First calculate crc32 checksum against fs uuid */
+               checksum = ext4_crc32c(EXT4_CRC32_INIT, sb->uuid,
+                               sizeof(sb->uuid));
+               /* Then calculate crc32 checksum against inode number
+                * and inode generation */
+               checksum = ext4_crc32c(checksum, &ino_index,
+                                    sizeof(ino_index));
+               checksum = ext4_crc32c(checksum, &ino_gen,
+                                    sizeof(ino_gen));
+               /* After that calculate crc32 checksum against all the dx_entry */
+               checksum = ext4_crc32c(checksum, dirent, size);
+               /* Finally calculate crc32 checksum for dx_tail */
+               checksum = ext4_crc32c(checksum, t,
+                               sizeof(struct ext4_dir_idx_tail));
+               t->checksum = orig_checksum;
+       }
+       return checksum;
+}
+
+static struct ext4_dir_idx_countlimit *
+ext4_dir_dx_get_countlimit(struct ext4_inode_ref *inode_ref,
+                       struct ext4_dir_entry_ll *dirent,
+                       int *offset)
+{
+       struct ext4_dir_entry_ll *dp;
+       struct ext4_dir_idx_root *root;
+       struct ext4_sblock *sb = &inode_ref->fs->sb;
+       int count_offset;
+
+       if (ext4_dir_entry_ll_get_entry_length(dirent) ==
+                       ext4_sb_get_block_size(sb))
+               count_offset = 8;
+       else if (ext4_dir_entry_ll_get_entry_length(dirent) == 12) {
+               root = (struct ext4_dir_idx_root *)dirent;
+               dp = (struct ext4_dir_entry_ll *)&root->dots[1];
+               if (ext4_dir_entry_ll_get_entry_length(dp) !=
+                   ext4_sb_get_block_size(sb) - 12)
+                       return NULL;
+               if (root->info.reserved_zero ||
+                   root->info.info_length != sizeof(struct ext4_dir_idx_root_info))
+                       return NULL;
+               count_offset = 32;
+       } else
+               return NULL;
+
+       if (offset)
+               *offset = count_offset;
+       return (struct ext4_dir_idx_countlimit *)(((char *)dirent) + count_offset);
+}
+
+/*
+ * BIG FAT NOTES:
+ *       Currently we do not verify the checksum of HTree node.
+ */
+static bool
+ext4_dir_dx_checksum_verify(struct ext4_inode_ref *inode_ref,
+                               struct ext4_dir_entry_ll *dirent)
+{
+       struct ext4_sblock *sb = &inode_ref->fs->sb;
+       int count_offset, limit, count;
+
+       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) {
+               struct ext4_dir_idx_countlimit *countlimit =
+                       ext4_dir_dx_get_countlimit(inode_ref, dirent, &count_offset);
+               if (!countlimit) {
+                       /* Directory seems corrupted. */
+                       return true;
+               }
+               struct ext4_dir_idx_tail *t;
+               limit = ext4_dir_dx_countlimit_get_limit(countlimit);
+               count = ext4_dir_dx_countlimit_get_count(countlimit);
+               if (count_offset + (limit * sizeof(struct ext4_dir_idx_entry)) >
+                               ext4_sb_get_block_size(sb) -
+                               sizeof(struct ext4_dir_idx_tail)) {
+                       /* There is no space to hold the checksum */
+                       return true;
+               }
+               t = (void *)(((struct ext4_dir_idx_entry *)countlimit) + limit);
+
+               if (t->checksum != to_le32(ext4_dir_dx_checksum(inode_ref,
+                                                               dirent,
+                                                               count_offset,
+                                                               count, t)))
+                       return false;
+       }
+       return true;
+}
+
+
+static void
+ext4_dir_set_dx_checksum(struct ext4_inode_ref *inode_ref,
+                       struct ext4_dir_entry_ll *dirent)
+{
+       int count_offset, limit, count;
+       struct ext4_sblock *sb = &inode_ref->fs->sb;
+
+       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) {
+               struct ext4_dir_idx_countlimit *countlimit =
+                       ext4_dir_dx_get_countlimit(inode_ref, dirent, &count_offset);
+               if (!countlimit) {
+                       /* Directory seems corrupted. */
+                       return;
+               }
+               struct ext4_dir_idx_tail *t;
+               limit = ext4_dir_dx_countlimit_get_limit(countlimit);
+               count = ext4_dir_dx_countlimit_get_count(countlimit);
+               if (count_offset + (limit * sizeof(struct ext4_dir_idx_entry)) >
+                               ext4_sb_get_block_size(sb) -
+                               sizeof(struct ext4_dir_idx_tail)) {
+                       /* There is no space to hold the checksum */
+                       return;
+               }
+               t = (struct ext4_dir_idx_tail *)
+                       (((struct ext4_dir_idx_entry *)countlimit) + limit);
+
+               t->checksum = to_le32(ext4_dir_dx_checksum(inode_ref, dirent,
+                                       count_offset, count, t));
+       }
+}
+#else
+#define ext4_dir_dx_checksum_verify(...) true
+#define ext4_dir_set_dx_checksum(...)
+#endif
+
 /****************************************************************************/
 
-int ext4_dir_dx_init(struct ext4_inode_ref *dir)
+int ext4_dir_dx_init(struct ext4_inode_ref *dir, struct ext4_inode_ref *parent)
 {
        /* Load block 0, where will be index root located */
-       uint32_t fblock;
-       int rc = ext4_fs_get_inode_data_block_index(dir, 0, &fblock);
+       ext4_fsblk_t fblock;
+       uint32_t iblock;
+       struct ext4_sblock *sb = &dir->fs->sb;
+       int rc = ext4_fs_append_inode_block(dir, &fblock, &iblock);
        if (rc != EOK)
                return rc;
 
        struct ext4_block block;
-       rc = ext4_block_get(dir->fs->bdev, &block, fblock);
+       rc = ext4_block_get_noread(dir->fs->bdev, &block, fblock);
        if (rc != EOK)
                return rc;
 
        /* Initialize pointers to data structures */
-       struct ext4_directory_dx_root *root = (void *)block.data;
-       struct ext4_directory_dx_root_info *info = &(root->info);
+       struct ext4_dir_idx_root *root = (void *)block.data;
+       struct ext4_dir_idx_root_info *info = &(root->info);
+
+       /* Initialize dot entries */
+       ext4_dir_write_entry(&dir->fs->sb,
+                       (struct ext4_dir_entry_ll *)root->dots,
+                       12,
+                       dir,
+                       ".",
+                       strlen("."));
+
+       ext4_dir_write_entry(&dir->fs->sb,
+                       (struct ext4_dir_entry_ll *)(root->dots + 1),
+                       ext4_sb_get_block_size(sb) - 12,
+                       parent,
+                       "..",
+                       strlen(".."));
 
        /* Initialize root info structure */
        uint8_t hash_version = ext4_get8(&dir->fs->sb, default_hash_version);
@@ -229,21 +392,24 @@ int ext4_dir_dx_init(struct ext4_inode_ref *dir)
        ext4_dir_dx_root_info_set_info_length(info, 8);
 
        /* Set limit and current number of entries */
-       struct ext4_directory_dx_countlimit *countlimit =
-           (struct ext4_directory_dx_countlimit *)&root->entries;
+       struct ext4_dir_idx_countlimit *countlimit =
+           (struct ext4_dir_idx_countlimit *)&root->entries;
 
        ext4_dir_dx_countlimit_set_count(countlimit, 1);
 
        uint32_t block_size = ext4_sb_get_block_size(&dir->fs->sb);
        uint32_t entry_space = block_size -
-                              2 * sizeof(struct ext4_directory_dx_dot_entry) -
-                              sizeof(struct ext4_directory_dx_root_info);
+                              2 * sizeof(struct ext4_dir_idx_dot_entry) -
+                              sizeof(struct ext4_dir_idx_root_info);
+       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM))
+               entry_space -= sizeof(struct ext4_dir_idx_tail);
+
        uint16_t root_limit =
-           entry_space / sizeof(struct ext4_directory_dx_entry);
+           entry_space / sizeof(struct ext4_dir_idx_entry);
+
        ext4_dir_dx_countlimit_set_limit(countlimit, root_limit);
 
        /* Append new block, where will be new entries inserted in the future */
-       uint32_t iblock;
        rc = ext4_fs_append_inode_block(dir, &fblock, &iblock);
        if (rc != EOK) {
                ext4_block_set(dir->fs->bdev, &block);
@@ -252,16 +418,34 @@ int ext4_dir_dx_init(struct ext4_inode_ref *dir)
 
        struct ext4_block new_block;
 
-       rc = ext4_block_get(dir->fs->bdev, &new_block, fblock);
+       rc = ext4_block_get_noread(dir->fs->bdev, &new_block, fblock);
        if (rc != EOK) {
                ext4_block_set(dir->fs->bdev, &block);
                return rc;
        }
 
        /* Fill the whole block with empty entry */
-       struct ext4_directory_entry_ll *block_entry = (void *)new_block.data;
+       struct ext4_dir_entry_ll *block_entry = (void *)new_block.data;
+
+       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) {
+               ext4_dir_entry_ll_set_entry_length(block_entry,
+                               block_size -
+                               sizeof(struct ext4_dir_entry_tail));
+               ext4_dir_entry_ll_set_name_length(sb,
+                                                 block_entry,
+                                                 0);
+               ext4_dir_entry_ll_set_inode_type(sb,
+                                                block_entry,
+                                                EXT4_DIRENTRY_UNKNOWN);
+
+               initialize_dir_tail(EXT4_DIRENT_TAIL(block_entry,
+                                       ext4_sb_get_block_size(sb)));
+               ext4_dir_set_checksum(dir,
+                               (struct ext4_dir_entry_ll *)new_block.data);
+       } else {
+               ext4_dir_entry_ll_set_entry_length(block_entry, block_size);
+       }
 
-       ext4_dir_entry_ll_set_entry_length(block_entry, block_size);
        ext4_dir_entry_ll_set_inode(block_entry, 0);
 
        new_block.dirty = true;
@@ -272,9 +456,11 @@ int ext4_dir_dx_init(struct ext4_inode_ref *dir)
        }
 
        /* Connect new block to the only entry in index */
-       struct ext4_directory_dx_entry *entry = root->entries;
+       struct ext4_dir_idx_entry *entry = root->entries;
        ext4_dir_dx_entry_set_block(entry, iblock);
 
+       ext4_dir_set_dx_checksum(dir,
+                       (struct ext4_dir_entry_ll *)block.data);
        block.dirty = true;
 
        return ext4_block_set(dir->fs->bdev, &block);
@@ -293,8 +479,8 @@ static int ext4_dir_hinfo_init(struct ext4_hash_info *hinfo,
                               struct ext4_sblock *sb, size_t name_len,
                               const char *name)
 {
-       struct ext4_directory_dx_root *root =
-           (struct ext4_directory_dx_root *)root_block->data;
+       struct ext4_dir_idx_root *root =
+           (struct ext4_dir_idx_root *)root_block->data;
 
        if ((root->info.hash_version != EXT2_HTREE_LEGACY) &&
            (root->info.hash_version != EXT2_HTREE_HALF_MD4) &&
@@ -312,12 +498,14 @@ static int ext4_dir_hinfo_init(struct ext4_hash_info *hinfo,
        /* Check if node limit is correct */
        uint32_t block_size = ext4_sb_get_block_size(sb);
        uint32_t entry_space = block_size;
-       entry_space -= 2 * sizeof(struct ext4_directory_dx_dot_entry);
-       entry_space -= sizeof(struct ext4_directory_dx_root_info);
-       entry_space = entry_space / sizeof(struct ext4_directory_dx_entry);
+       entry_space -= 2 * sizeof(struct ext4_dir_idx_dot_entry);
+       entry_space -= sizeof(struct ext4_dir_idx_root_info);
+       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM))
+               entry_space -= sizeof(struct ext4_dir_idx_tail);
+       entry_space = entry_space / sizeof(struct ext4_dir_idx_entry);
 
        uint16_t limit = ext4_dir_dx_countlimit_get_limit(
-           (struct ext4_directory_dx_countlimit *)&root->entries);
+           (struct ext4_dir_idx_countlimit *)&root->entries);
        if (limit != entry_space)
                return EXT4_ERR_BAD_DX_DIR;
 
@@ -352,30 +540,30 @@ static int ext4_dir_hinfo_init(struct ext4_hash_info *hinfo,
 static int ext4_dir_dx_get_leaf(struct ext4_hash_info *hinfo,
                                struct ext4_inode_ref *inode_ref,
                                struct ext4_block *root_block,
-                               struct ext4_directory_dx_block **dx_block,
-                               struct ext4_directory_dx_block *dx_blocks)
+                               struct ext4_dir_idx_block **dx_block,
+                               struct ext4_dir_idx_block *dx_blocks)
 {
-       struct ext4_directory_dx_block *tmp_dx_block = dx_blocks;
-       struct ext4_directory_dx_root *root =
-           (struct ext4_directory_dx_root *)root_block->data;
-       struct ext4_directory_dx_entry *entries =
-           (struct ext4_directory_dx_entry *)&root->entries;
+       struct ext4_dir_idx_block *tmp_dx_block = dx_blocks;
+       struct ext4_dir_idx_root *root =
+           (struct ext4_dir_idx_root *)root_block->data;
+       struct ext4_dir_idx_entry *entries =
+           (struct ext4_dir_idx_entry *)&root->entries;
 
        uint16_t limit = ext4_dir_dx_countlimit_get_limit(
-           (struct ext4_directory_dx_countlimit *)entries);
+           (struct ext4_dir_idx_countlimit *)entries);
        uint8_t indirect_level =
            ext4_dir_dx_root_info_get_indirect_levels(&root->info);
 
        struct ext4_block *tmp_block = root_block;
-       struct ext4_directory_dx_entry *p;
-       struct ext4_directory_dx_entry *q;
-       struct ext4_directory_dx_entry *m;
-       struct ext4_directory_dx_entry *at;
+       struct ext4_dir_idx_entry *p;
+       struct ext4_dir_idx_entry *q;
+       struct ext4_dir_idx_entry *m;
+       struct ext4_dir_idx_entry *at;
 
        /* Walk through the index tree */
        while (true) {
                uint16_t count = ext4_dir_dx_countlimit_get_count(
-                   (struct ext4_directory_dx_countlimit *)entries);
+                   (struct ext4_dir_idx_countlimit *)entries);
                if ((count == 0) || (count > limit))
                        return EXT4_ERR_BAD_DX_DIR;
 
@@ -411,9 +599,9 @@ static int ext4_dir_dx_get_leaf(struct ext4_hash_info *hinfo,
 
                indirect_level--;
 
-               uint32_t fblock;
+               ext4_fsblk_t fblock;
                int rc = ext4_fs_get_inode_data_block_index(
-                   inode_ref, next_block, &fblock);
+                   inode_ref, next_block, &fblock, false);
                if (rc != EOK)
                        return rc;
 
@@ -422,22 +610,34 @@ static int ext4_dir_dx_get_leaf(struct ext4_hash_info *hinfo,
                        return rc;
 
                entries =
-                   ((struct ext4_directory_dx_node *)tmp_block->data)->entries;
+                   ((struct ext4_dir_idx_node *)tmp_block->data)->entries;
                limit = ext4_dir_dx_countlimit_get_limit(
-                   (struct ext4_directory_dx_countlimit *)entries);
+                   (struct ext4_dir_idx_countlimit *)entries);
+
+               struct ext4_sblock *sb = &inode_ref->fs->sb;
+               uint16_t entry_space = ext4_sb_get_block_size(sb) -
+                               sizeof(struct ext4_fake_dir_entry);
 
-               uint16_t entry_space =
-                   ext4_sb_get_block_size(&inode_ref->fs->sb) -
-                   sizeof(struct ext4_fake_directory_entry);
+               if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM))
+                       entry_space -= sizeof(struct ext4_dir_idx_tail);
 
-               entry_space =
-                   entry_space / sizeof(struct ext4_directory_dx_entry);
+               entry_space = entry_space / sizeof(struct ext4_dir_idx_entry);
 
                if (limit != entry_space) {
                        ext4_block_set(inode_ref->fs->bdev, tmp_block);
                        return EXT4_ERR_BAD_DX_DIR;
                }
 
+               if (!ext4_dir_dx_checksum_verify(inode_ref,
+                               (struct ext4_dir_entry_ll *)tmp_block->data)) {
+                       ext4_dbg(DEBUG_DIR_IDX,
+                                       DBG_WARN "HTree checksum failed."
+                                       "Inode: %" PRIu32", "
+                                       "Block: %" PRIu32"\n",
+                                       inode_ref->index,
+                                       next_block);
+               }
+
                ++tmp_dx_block;
        }
 
@@ -454,17 +654,17 @@ static int ext4_dir_dx_get_leaf(struct ext4_hash_info *hinfo,
  */
 static int ext4_dir_dx_next_block(struct ext4_inode_ref *inode_ref,
                                  uint32_t hash,
-                                 struct ext4_directory_dx_block *dx_block,
-                                 struct ext4_directory_dx_block *dx_blocks)
+                                 struct ext4_dir_idx_block *dx_block,
+                                 struct ext4_dir_idx_block *dx_blocks)
 {
        uint32_t num_handles = 0;
-       struct ext4_directory_dx_block *p = dx_block;
+       struct ext4_dir_idx_block *p = dx_block;
 
        /* Try to find data block with next bunch of entries */
        while (true) {
                p->position++;
                uint16_t count = ext4_dir_dx_countlimit_get_count(
-                   (struct ext4_directory_dx_countlimit *)p->entries);
+                   (struct ext4_dir_idx_countlimit *)p->entries);
 
                if (p->position < p->entries + count)
                        break;
@@ -487,10 +687,10 @@ static int ext4_dir_dx_next_block(struct ext4_inode_ref *inode_ref,
        /* Fill new path */
        while (num_handles--) {
                uint32_t block_idx = ext4_dir_dx_entry_get_block(p->position);
-               uint32_t block_addr;
+               ext4_fsblk_t block_addr;
 
                int rc = ext4_fs_get_inode_data_block_index(
-                   inode_ref, block_idx, &block_addr);
+                   inode_ref, block_idx, &block_addr, false);
                if (rc != EOK)
                        return rc;
 
@@ -499,6 +699,16 @@ static int ext4_dir_dx_next_block(struct ext4_inode_ref *inode_ref,
                if (rc != EOK)
                        return rc;
 
+               if (!ext4_dir_dx_checksum_verify(inode_ref,
+                               (struct ext4_dir_entry_ll *)block.data)) {
+                       ext4_dbg(DEBUG_DIR_IDX,
+                                       DBG_WARN "HTree checksum failed."
+                                       "Inode: %" PRIu32", "
+                                       "Block: %" PRIu32"\n",
+                                       inode_ref->index,
+                                       block_idx);
+               }
+
                p++;
 
                /* Don't forget to put old block (prevent memory leak) */
@@ -506,24 +716,25 @@ static int ext4_dir_dx_next_block(struct ext4_inode_ref *inode_ref,
                if (rc != EOK)
                        return rc;
 
-               memcpy(&p->block, &p->block, sizeof(block));
+               memcpy(&p->block, &block, sizeof(block));
                p->entries =
-                   ((struct ext4_directory_dx_node *)block.data)->entries;
+                   ((struct ext4_dir_idx_node *)block.data)->entries;
                p->position = p->entries;
        }
 
        return ENOENT;
 }
 
-int ext4_dir_dx_find_entry(struct ext4_directory_search_result *result,
+int ext4_dir_dx_find_entry(struct ext4_dir_search_result *result,
                           struct ext4_inode_ref *inode_ref, size_t name_len,
                           const char *name)
 {
        /* Load direct block 0 (index root) */
-       uint32_t root_block_addr;
+       ext4_fsblk_t root_block_addr;
        int rc2;
        int rc =
-           ext4_fs_get_inode_data_block_index(inode_ref, 0, &root_block_addr);
+           ext4_fs_get_inode_data_block_index(inode_ref,
+                           0, &root_block_addr, false);
        if (rc != EOK)
                return rc;
 
@@ -534,6 +745,16 @@ int ext4_dir_dx_find_entry(struct ext4_directory_search_result *result,
        if (rc != EOK)
                return rc;
 
+       if (!ext4_dir_dx_checksum_verify(inode_ref,
+                               (struct ext4_dir_entry_ll *)root_block.data)) {
+               ext4_dbg(DEBUG_DIR_IDX,
+                        DBG_WARN "HTree root checksum failed."
+                        "Inode: %" PRIu32", "
+                        "Block: %" PRIu32"\n",
+                        inode_ref->index,
+                        (uint32_t)0);
+       }
+
        /* Initialize hash info (compute hash value) */
        struct ext4_hash_info hinfo;
        rc = ext4_dir_hinfo_init(&hinfo, &root_block, &fs->sb, name_len, name);
@@ -546,9 +767,9 @@ int ext4_dir_dx_find_entry(struct ext4_directory_search_result *result,
         * Hardcoded number 2 means maximum height of index tree,
         * specified in the Linux driver.
         */
-       struct ext4_directory_dx_block dx_blocks[2];
-       struct ext4_directory_dx_block *dx_block;
-       struct ext4_directory_dx_block *tmp;
+       struct ext4_dir_idx_block dx_blocks[2];
+       struct ext4_dir_idx_block *dx_block;
+       struct ext4_dir_idx_block *tmp;
 
        rc = ext4_dir_dx_get_leaf(&hinfo, inode_ref, &root_block, &dx_block,
                                  dx_blocks);
@@ -561,10 +782,11 @@ int ext4_dir_dx_find_entry(struct ext4_directory_search_result *result,
                /* Load leaf block */
                uint32_t leaf_block_idx =
                    ext4_dir_dx_entry_get_block(dx_block->position);
-               uint32_t leaf_block_addr;
+               ext4_fsblk_t leaf_block_addr;
 
                rc = ext4_fs_get_inode_data_block_index(
-                   inode_ref, leaf_block_idx, &leaf_block_addr);
+                   inode_ref, leaf_block_idx, &leaf_block_addr,
+                   false);
                if (rc != EOK)
                        goto cleanup;
 
@@ -573,8 +795,18 @@ int ext4_dir_dx_find_entry(struct ext4_directory_search_result *result,
                if (rc != EOK)
                        goto cleanup;
 
+               if (!ext4_dir_checksum_verify(inode_ref,
+                               (struct ext4_dir_entry_ll *)leaf_block.data)) {
+                       ext4_dbg(DEBUG_DIR_IDX,
+                                DBG_WARN "HTree leaf block checksum failed."
+                                "Inode: %" PRIu32", "
+                                "Block: %" PRIu32"\n",
+                                inode_ref->index,
+                                leaf_block_idx);
+               }
+
                /* Linear search inside block */
-               struct ext4_directory_entry_ll *res_dentry;
+               struct ext4_dir_entry_ll *res_dentry;
                rc = ext4_dir_find_in_block(&leaf_block, &fs->sb, name_len,
                                            name, &res_dentry);
 
@@ -679,23 +911,25 @@ static int ext4_dir_dx_entry_comparator(const void *arg1, const void *arg2)
 
 /**@brief  Insert new index entry to block.
  *         Note that space for new entry must be checked by caller.
+ * @param inode_ref   Directory i-node
  * @param index_block Block where to insert new entry
  * @param hash        Hash value covered by child node
  * @param iblock      Logical number of child block
  *
  */
 static void
-ext4_dir_dx_insert_entry(struct ext4_directory_dx_block *index_block,
+ext4_dir_dx_insert_entry(struct ext4_inode_ref *inode_ref __unused,
+                        struct ext4_dir_idx_block *index_block,
                         uint32_t hash, uint32_t iblock)
 {
-       struct ext4_directory_dx_entry *old_index_entry = index_block->position;
-       struct ext4_directory_dx_entry *new_index_entry = old_index_entry + 1;
+       struct ext4_dir_idx_entry *old_index_entry = index_block->position;
+       struct ext4_dir_idx_entry *new_index_entry = old_index_entry + 1;
 
-       struct ext4_directory_dx_countlimit *countlimit =
-           (struct ext4_directory_dx_countlimit *)index_block->entries;
+       struct ext4_dir_idx_countlimit *countlimit =
+           (struct ext4_dir_idx_countlimit *)index_block->entries;
        uint32_t count = ext4_dir_dx_countlimit_get_count(countlimit);
 
-       struct ext4_directory_dx_entry *start_index = index_block->entries;
+       struct ext4_dir_idx_entry *start_index = index_block->entries;
        size_t bytes =
            (uint8_t *)(start_index + count) - (uint8_t *)(new_index_entry);
 
@@ -706,6 +940,8 @@ ext4_dir_dx_insert_entry(struct ext4_directory_dx_block *index_block,
 
        ext4_dir_dx_countlimit_set_count(countlimit, count + 1);
 
+       ext4_dir_set_dx_checksum(inode_ref,
+                       (struct ext4_dir_entry_ll *)index_block->block.data);
        index_block->block.dirty = true;
 }
 
@@ -719,7 +955,7 @@ ext4_dir_dx_insert_entry(struct ext4_directory_dx_block *index_block,
 static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
                                  struct ext4_hash_info *hinfo,
                                  struct ext4_block *old_data_block,
-                                 struct ext4_directory_dx_block *index_block,
+                                 struct ext4_dir_idx_block *index_block,
                                  struct ext4_block *new_data_block)
 {
        int rc = EOK;
@@ -733,7 +969,7 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
 
        /* dot entry has the smallest size available */
        uint32_t max_entry_count =
-           block_size / sizeof(struct ext4_directory_dx_dot_entry);
+           block_size / sizeof(struct ext4_dir_idx_dot_entry);
 
        /* Allocate sort entry */
        struct ext4_dx_sort_entry *sort_array =
@@ -752,12 +988,11 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
        memcpy(&tmp_hinfo, hinfo, sizeof(struct ext4_hash_info));
 
        /* Load all valid entries to the buffer */
-       struct ext4_directory_entry_ll *dentry = (void *)old_data_block->data;
+       struct ext4_dir_entry_ll *dentry = (void *)old_data_block->data;
        uint8_t *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) &&
-                   dentry->name_length) {
+               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);
 
@@ -797,7 +1032,7 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
              ext4_dir_dx_entry_comparator);
 #endif
        /* Allocate new block for store the second part of entries */
-       uint32_t new_fblock;
+       ext4_fsblk_t new_fblock;
        uint32_t new_iblock;
        rc = ext4_fs_append_inode_block(inode_ref, &new_fblock, &new_iblock);
        if (rc != EOK) {
@@ -808,8 +1043,8 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
 
        /* Load new block */
        struct ext4_block new_data_block_tmp;
-       rc = ext4_block_get(inode_ref->fs->bdev, &new_data_block_tmp,
-                           new_fblock);
+       rc = ext4_block_get_noread(inode_ref->fs->bdev, &new_data_block_tmp,
+                                  new_fblock);
        if (rc != EOK) {
                free(sort_array);
                free(entry_buffer);
@@ -841,13 +1076,16 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
 
        uint32_t offset = 0;
        void *ptr;
+       struct ext4_sblock *sb = &inode_ref->fs->sb;
+       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM))
+               block_size -= sizeof(struct ext4_dir_entry_tail);
 
        /* First part - to the old block */
        for (i = 0; i < mid; ++i) {
                ptr = old_data_block->data + offset;
                memcpy(ptr, sort_array[i].dentry, sort_array[i].rec_len);
 
-               struct ext4_directory_entry_ll *tmp = ptr;
+               struct ext4_dir_entry_ll *tmp = ptr;
                if (i < (mid - 1))
                        ext4_dir_entry_ll_set_entry_length(
                            tmp, sort_array[i].rec_len);
@@ -864,7 +1102,7 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
                ptr = new_data_block_tmp.data + offset;
                memcpy(ptr, sort_array[i].dentry, sort_array[i].rec_len);
 
-               struct ext4_directory_entry_ll *tmp = ptr;
+               struct ext4_dir_entry_ll *tmp = ptr;
                if (i < (idx - 1))
                        ext4_dir_entry_ll_set_entry_length(
                            tmp, sort_array[i].rec_len);
@@ -875,14 +1113,29 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,
                offset += sort_array[i].rec_len;
        }
 
+       block_size = ext4_sb_get_block_size(&inode_ref->fs->sb);
+
        /* Do some steps to finish operation */
+       sb = &inode_ref->fs->sb;
+       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) {
+               initialize_dir_tail(EXT4_DIRENT_TAIL(old_data_block->data,
+                                       block_size));
+               initialize_dir_tail(EXT4_DIRENT_TAIL(new_data_block_tmp.data,
+                                       block_size));
+       }
+       ext4_dir_set_checksum(inode_ref,
+                       (struct ext4_dir_entry_ll *)old_data_block->data);
+       ext4_dir_set_checksum(inode_ref,
+                       (struct ext4_dir_entry_ll *)new_data_block_tmp.data);
        old_data_block->dirty = true;
        new_data_block_tmp.dirty = true;
 
        free(sort_array);
        free(entry_buffer);
 
-       ext4_dir_dx_insert_entry(index_block, new_hash + continued, new_iblock);
+       ext4_dir_dx_insert_entry(inode_ref,
+                       index_block,
+                       new_hash + continued, new_iblock);
 
        *new_data_block = new_data_block_tmp;
 
@@ -897,23 +1150,24 @@ 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,
-                       struct ext4_directory_dx_block *dx_blocks,
-                       struct ext4_directory_dx_block *dx_block,
-                       struct ext4_directory_dx_block **new_dx_block)
+                       struct ext4_dir_idx_block *dx_blocks,
+                       struct ext4_dir_idx_block *dx_block,
+                       struct ext4_dir_idx_block **new_dx_block)
 {
-       struct ext4_directory_dx_entry *entries;
+       struct ext4_sblock *sb = &inode_ref->fs->sb;
+       struct ext4_dir_idx_entry *entries;
 
        if (dx_block == dx_blocks)
                entries =
-                   ((struct ext4_directory_dx_root *)dx_block->block.data)
+                   ((struct ext4_dir_idx_root *)dx_block->block.data)
                        ->entries;
        else
                entries =
-                   ((struct ext4_directory_dx_node *)dx_block->block.data)
+                   ((struct ext4_dir_idx_node *)dx_block->block.data)
                        ->entries;
 
-       struct ext4_directory_dx_countlimit *countlimit =
-           (struct ext4_directory_dx_countlimit *)entries;
+       struct ext4_dir_idx_countlimit *countlimit =
+           (struct ext4_dir_idx_countlimit *)entries;
 
        uint16_t leaf_limit = ext4_dir_dx_countlimit_get_limit(countlimit);
        uint16_t leaf_count = ext4_dir_dx_countlimit_get_count(countlimit);
@@ -922,12 +1176,12 @@ ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
        if (leaf_limit == leaf_count) {
                size_t levels = dx_block - dx_blocks;
 
-               struct ext4_directory_dx_entry *root_entries =
-                   ((struct ext4_directory_dx_root *)dx_blocks[0].block.data)
+               struct ext4_dir_idx_entry *root_entries =
+                   ((struct ext4_dir_idx_root *)dx_blocks[0].block.data)
                        ->entries;
 
-               struct ext4_directory_dx_countlimit *root_countlimit =
-                   (struct ext4_directory_dx_countlimit *)root_entries;
+               struct ext4_dir_idx_countlimit *root_countlimit =
+                   (struct ext4_dir_idx_countlimit *)root_entries;
                uint16_t root_limit =
                    ext4_dir_dx_countlimit_get_limit(root_countlimit);
                uint16_t root_count =
@@ -938,7 +1192,7 @@ ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
                        return ENOSPC;
 
                /* Add new block to directory */
-               uint32_t new_fblock;
+               ext4_fsblk_t new_fblock;
                uint32_t new_iblock;
                int rc = ext4_fs_append_inode_block(inode_ref, &new_fblock,
                                                    &new_iblock);
@@ -948,16 +1202,17 @@ ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
                /* load new block */
                struct ext4_block new_block;
                rc =
-                   ext4_block_get(inode_ref->fs->bdev, &new_block, new_fblock);
+                   ext4_block_get_noread(inode_ref->fs->bdev,
+                                         &new_block, new_fblock);
                if (rc != EOK)
                        return rc;
 
-               struct ext4_directory_dx_node *new_node =
+               struct ext4_dir_idx_node *new_node =
                    (void *)new_block.data;
-               struct ext4_directory_dx_entry *new_entries = new_node->entries;
+               struct ext4_dir_idx_entry *new_entries = new_node->entries;
 
                memset(&new_node->fake, 0,
-                      sizeof(struct ext4_fake_directory_entry));
+                      sizeof(struct ext4_fake_dir_entry));
 
                uint32_t block_size =
                    ext4_sb_get_block_size(&inode_ref->fs->sb);
@@ -975,13 +1230,13 @@ ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
                        memcpy((void *)new_entries,
                               (void *)(entries + count_left),
                               count_right *
-                                  sizeof(struct ext4_directory_dx_entry));
+                                  sizeof(struct ext4_dir_idx_entry));
 
                        /* Initialize new node */
-                       struct ext4_directory_dx_countlimit *left_countlimit =
-                           (struct ext4_directory_dx_countlimit *)entries;
-                       struct ext4_directory_dx_countlimit *right_countlimit =
-                           (struct ext4_directory_dx_countlimit *)new_entries;
+                       struct ext4_dir_idx_countlimit *left_countlimit =
+                           (struct ext4_dir_idx_countlimit *)entries;
+                       struct ext4_dir_idx_countlimit *right_countlimit =
+                           (struct ext4_dir_idx_countlimit *)new_entries;
 
                        ext4_dir_dx_countlimit_set_count(left_countlimit,
                                                         count_left);
@@ -990,10 +1245,13 @@ ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
 
                        uint32_t entry_space =
                            block_size -
-                           sizeof(struct ext4_fake_directory_entry);
+                           sizeof(struct ext4_fake_dir_entry);
+                       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM))
+                               entry_space -= sizeof(struct ext4_dir_idx_tail);
+
                        uint32_t node_limit =
-                           entry_space /
-                           sizeof(struct ext4_directory_dx_entry);
+                           entry_space / sizeof(struct ext4_dir_idx_entry);
+
                        ext4_dir_dx_countlimit_set_limit(right_countlimit,
                                                         node_limit);
 
@@ -1001,6 +1259,10 @@ ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
                        uint32_t position_index =
                            (dx_block->position - dx_block->entries);
                        if (position_index >= count_left) {
+                               ext4_dir_set_dx_checksum(
+                                               inode_ref,
+                                               (struct ext4_dir_entry_ll *)
+                                               dx_block->block.data);
                                dx_block->block.dirty = true;
 
                                struct ext4_block block_tmp = dx_block->block;
@@ -1015,11 +1277,21 @@ ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
                        }
 
                        /* Finally insert new entry */
-                       ext4_dir_dx_insert_entry(dx_blocks, hash_right,
+                       ext4_dir_dx_insert_entry(inode_ref,
+                                                dx_blocks, hash_right,
                                                 new_iblock);
+                       ext4_dir_set_dx_checksum(inode_ref,
+                                               (struct ext4_dir_entry_ll *)
+                                                       dx_blocks[0].block.data);
+                       ext4_dir_set_dx_checksum(inode_ref,
+                                               (struct ext4_dir_entry_ll *)
+                                                       dx_blocks[1].block.data);
                        dx_blocks[0].block.dirty = true;
                        dx_blocks[1].block.dirty = true;
 
+                       ext4_dir_set_dx_checksum(inode_ref,
+                                               (struct ext4_dir_entry_ll *)
+                                                       new_block.data);
                        new_block.dirty = true;
                        return ext4_block_set(inode_ref->fs->bdev, &new_block);
                } else {
@@ -1028,30 +1300,32 @@ ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
                        /* Copy data from root to child block */
                        memcpy((void *)new_entries, (void *)entries,
                               leaf_count *
-                                  sizeof(struct ext4_directory_dx_entry));
+                                  sizeof(struct ext4_dir_idx_entry));
 
-                       struct ext4_directory_dx_countlimit *new_countlimit =
-                           (struct ext4_directory_dx_countlimit *)new_entries;
+                       struct ext4_dir_idx_countlimit *new_countlimit =
+                           (struct ext4_dir_idx_countlimit *)new_entries;
 
                        uint32_t entry_space =
                            block_size -
-                           sizeof(struct ext4_fake_directory_entry);
+                           sizeof(struct ext4_fake_dir_entry);
+                       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM))
+                               entry_space -= sizeof(struct ext4_dir_idx_tail);
+
                        uint32_t node_limit =
-                           entry_space /
-                           sizeof(struct ext4_directory_dx_entry);
+                           entry_space / sizeof(struct ext4_dir_idx_entry);
                        ext4_dir_dx_countlimit_set_limit(new_countlimit,
                                                         node_limit);
 
                        /* Set values in root node */
-                       struct ext4_directory_dx_countlimit
+                       struct ext4_dir_idx_countlimit
                            *new_root_countlimit =
-                               (struct ext4_directory_dx_countlimit *)entries;
+                               (struct ext4_dir_idx_countlimit *)entries;
 
                        ext4_dir_dx_countlimit_set_count(new_root_countlimit,
                                                         1);
                        ext4_dir_dx_entry_set_block(entries, new_iblock);
 
-                       ((struct ext4_directory_dx_root *)dx_blocks[0]
+                       ((struct ext4_dir_idx_root *)dx_blocks[0]
                             .block.data)
                            ->info.indirect_levels = 1;
 
@@ -1064,6 +1338,12 @@ ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
 
                        *new_dx_block = dx_block;
 
+                       ext4_dir_set_dx_checksum(inode_ref,
+                                               (struct ext4_dir_entry_ll *)
+                                                       dx_blocks[0].block.data);
+                       ext4_dir_set_dx_checksum(inode_ref,
+                                               (struct ext4_dir_entry_ll *)
+                                                       dx_blocks[1].block.data);
                        dx_blocks[0].block.dirty = true;
                        dx_blocks[1].block.dirty = true;
                }
@@ -1078,9 +1358,11 @@ int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent,
        int rc2 = EOK;
 
        /* Get direct block 0 (index root) */
-       uint32_t root_block_addr;
+       ext4_fsblk_t root_block_addr;
        int rc =
-           ext4_fs_get_inode_data_block_index(parent, 0, &root_block_addr);
+           ext4_fs_get_inode_data_block_index(parent,
+                           0, &root_block_addr,
+                           false);
        if (rc != EOK)
                return rc;
 
@@ -1091,6 +1373,16 @@ int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent,
        if (rc != EOK)
                return rc;
 
+       if (!ext4_dir_dx_checksum_verify(parent,
+                       (struct ext4_dir_entry_ll *)root_block.data)) {
+               ext4_dbg(DEBUG_DIR_IDX,
+                        DBG_WARN "HTree root checksum failed."
+                        "Inode: %" PRIu32", "
+                        "Block: %" PRIu32"\n",
+                        parent->index,
+                        (uint32_t)0);
+       }
+
        /* Initialize hinfo structure (mainly compute hash) */
        uint32_t name_len = strlen(name);
        struct ext4_hash_info hinfo;
@@ -1104,9 +1396,9 @@ int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent,
         * Hardcoded number 2 means maximum height of index
         * tree defined in Linux.
         */
-       struct ext4_directory_dx_block dx_blocks[2];
-       struct ext4_directory_dx_block *dx_block;
-       struct ext4_directory_dx_block *dx_it;
+       struct ext4_dir_idx_block dx_blocks[2];
+       struct ext4_dir_idx_block *dx_block;
+       struct ext4_dir_idx_block *dx_it;
 
        rc = ext4_dir_dx_get_leaf(&hinfo, parent, &root_block, &dx_block,
                                  dx_blocks);
@@ -1118,9 +1410,10 @@ int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent,
        /* Try to insert to existing data block */
        uint32_t leaf_block_idx =
            ext4_dir_dx_entry_get_block(dx_block->position);
-       uint32_t leaf_block_addr;
+       ext4_fsblk_t leaf_block_addr;
        rc = ext4_fs_get_inode_data_block_index(parent, leaf_block_idx,
-                                               &leaf_block_addr);
+                                               &leaf_block_addr,
+                                               false);
        if (rc != EOK)
                goto release_index;
 
@@ -1137,9 +1430,19 @@ int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent,
        if (rc != EOK)
                goto release_index;
 
+       if (!ext4_dir_checksum_verify(parent,
+                       (struct ext4_dir_entry_ll *)target_block.data)) {
+               ext4_dbg(DEBUG_DIR_IDX,
+                               DBG_WARN "HTree leaf block checksum failed."
+                               "Inode: %" PRIu32", "
+                               "Block: %" PRIu32"\n",
+                               parent->index,
+                               leaf_block_idx);
+       }
+
        /* Check if insert operation passed */
-       rc = ext4_dir_try_insert_entry(&fs->sb, &target_block, child, name,
-                                      name_len);
+       rc = ext4_dir_try_insert_entry(&fs->sb, parent, &target_block, child,
+                                       name, name_len);
        if (rc == EOK)
                goto release_target_index;
 
@@ -1156,11 +1459,11 @@ int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent,
        uint32_t new_block_hash =
            ext4_dir_dx_entry_get_hash(dx_block->position + 1);
        if (hinfo.hash >= new_block_hash)
-               rc = ext4_dir_try_insert_entry(&fs->sb, &new_block, child, name,
-                                              name_len);
+               rc = ext4_dir_try_insert_entry(&fs->sb, parent, &new_block,
+                               child, name, name_len);
        else
-               rc = ext4_dir_try_insert_entry(&fs->sb, &target_block, child,
-                                              name, name_len);
+               rc = ext4_dir_try_insert_entry(&fs->sb, parent, &target_block,
+                               child, name, name_len);
 
        /* Cleanup */
        rc = ext4_block_set(fs->bdev, &new_block);
@@ -1197,8 +1500,8 @@ int ext4_dir_dx_reset_parent_inode(struct ext4_inode_ref *dir,
                                    uint32_t parent_inode)
 {
        /* Load block 0, where will be index root located */
-       uint32_t fblock;
-       int rc = ext4_fs_get_inode_data_block_index(dir, 0, &fblock);
+       ext4_fsblk_t fblock;
+       int rc = ext4_fs_get_inode_data_block_index(dir, 0, &fblock, false);
        if (rc != EOK)
                return rc;
 
@@ -1207,12 +1510,25 @@ int ext4_dir_dx_reset_parent_inode(struct ext4_inode_ref *dir,
        if (rc != EOK)
                return rc;
 
+       if (!ext4_dir_dx_checksum_verify(dir,
+                       (struct ext4_dir_entry_ll *)block.data)) {
+               ext4_dbg(DEBUG_DIR_IDX,
+                        DBG_WARN "HTree root checksum failed."
+                        "Inode: %" PRIu32", "
+                        "Block: %" PRIu32"\n",
+                        dir->index,
+                        (uint32_t)0);
+       }
+
        /* Initialize pointers to data structures */
-       struct ext4_directory_dx_root *root = (void *)block.data;
+       struct ext4_dir_idx_root *root = (void *)block.data;
 
        /* Fill the inode field with a new parent ino. */
        ext4_dx_dot_entry_set_inode(&root->dots[1], parent_inode);
 
+       ext4_dir_set_dx_checksum(dir,
+                               (struct ext4_dir_entry_ll *)
+                                       block.data);
        block.dirty = true;
 
        return ext4_block_set(dir->fs->bdev, &block);