Do not verify checksum upon seeking in the directory.
[lwext4.git] / lwext4 / ext4_dir_idx.c
index fcf65472d375e826afe9fe4cb05846e1660c30fe..59f0c5675298efb199ef58b227be5501bd9af1ee 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>
@@ -202,13 +204,159 @@ 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_directory_dx_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_directory_dx_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_directory_dx_tail));
+               t->checksum = orig_checksum;
+       }
+       return checksum;
+}
+
+static struct ext4_directory_dx_countlimit *
+ext4_dir_dx_get_countlimit(struct ext4_inode_ref *inode_ref,
+                       struct ext4_directory_entry_ll *dirent,
+                       int *offset)
+{
+       struct ext4_directory_entry_ll *dp;
+       struct ext4_directory_dx_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_directory_dx_root *)dirent;
+               dp = (struct ext4_directory_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_directory_dx_root_info))
+                       return NULL;
+               count_offset = 32;
+       } else
+               return NULL;
+
+       if (offset)
+               *offset = count_offset;
+       return (struct ext4_directory_dx_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_directory_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_directory_dx_countlimit *countlimit =
+                       ext4_dir_dx_get_countlimit(inode_ref, dirent, &count_offset);
+               if (!countlimit) {
+                       /* Directory seems corrupted. */
+                       return true;
+               }
+               struct ext4_directory_dx_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_directory_dx_entry)) >
+                               ext4_sb_get_block_size(sb) -
+                               sizeof(struct ext4_directory_dx_tail)) {
+                       /* There is no space to hold the checksum */
+                       return true;
+               }
+               t = (struct ext4_directory_dx_tail *)
+                       (((struct ext4_directory_dx_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_directory_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_directory_dx_countlimit *countlimit =
+                       ext4_dir_dx_get_countlimit(inode_ref, dirent, &count_offset);
+               if (!countlimit) {
+                       /* Directory seems corrupted. */
+                       return;
+               }
+               struct ext4_directory_dx_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_directory_dx_entry)) >
+                               ext4_sb_get_block_size(sb) -
+                               sizeof(struct ext4_directory_dx_tail)) {
+                       /* There is no space to hold the checksum */
+                       return;
+               }
+               t = (struct ext4_directory_dx_tail *)
+                       (((struct ext4_directory_dx_entry *)countlimit) + limit);
+
+               t->checksum =
+                       to_le32(ext4_dir_dx_checksum(inode_ref, dirent, count_offset, count, t));
+       }
+}
+#else
+#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 */
        ext4_fsblk_t fblock;
-       int rc = ext4_fs_get_inode_data_block_index(dir, 0, &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;
 
@@ -221,6 +369,21 @@ int ext4_dir_dx_init(struct ext4_inode_ref *dir)
        struct ext4_directory_dx_root *root = (void *)block.data;
        struct ext4_directory_dx_root_info *info = &(root->info);
 
+       /* Initialize dot entries */
+       ext4_dir_write_entry(&dir->fs->sb,
+                       (struct ext4_directory_entry_ll *)root->dots,
+                       12,
+                       dir,
+                       ".",
+                       strlen("."));
+
+       ext4_dir_write_entry(&dir->fs->sb,
+                       (struct ext4_directory_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);
 
@@ -238,12 +401,15 @@ int ext4_dir_dx_init(struct ext4_inode_ref *dir)
        uint32_t entry_space = block_size -
                               2 * sizeof(struct ext4_directory_dx_dot_entry) -
                               sizeof(struct ext4_directory_dx_root_info);
+       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM))
+               entry_space -= sizeof(struct ext4_directory_dx_tail);
+
        uint16_t root_limit =
            entry_space / sizeof(struct ext4_directory_dx_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);
@@ -261,7 +427,25 @@ int ext4_dir_dx_init(struct ext4_inode_ref *dir)
        /* Fill the whole block with empty entry */
        struct ext4_directory_entry_ll *block_entry = (void *)new_block.data;
 
-       ext4_dir_entry_ll_set_entry_length(block_entry, block_size);
+       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_directory_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_directory_entry_ll *)new_block.data);
+       } else {
+               ext4_dir_entry_ll_set_entry_length(block_entry, block_size);
+       }
+
        ext4_dir_entry_ll_set_inode(block_entry, 0);
 
        new_block.dirty = true;
@@ -275,6 +459,8 @@ int ext4_dir_dx_init(struct ext4_inode_ref *dir)
        struct ext4_directory_dx_entry *entry = root->entries;
        ext4_dir_dx_entry_set_block(entry, iblock);
 
+       ext4_dir_set_dx_checksum(dir,
+                       (struct ext4_directory_entry_ll *)block.data);
        block.dirty = true;
 
        return ext4_block_set(dir->fs->bdev, &block);
@@ -314,6 +500,8 @@ static int ext4_dir_hinfo_init(struct ext4_hash_info *hinfo,
        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);
+       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM))
+               entry_space -= sizeof(struct ext4_directory_dx_tail);
        entry_space = entry_space / sizeof(struct ext4_directory_dx_entry);
 
        uint16_t limit = ext4_dir_dx_countlimit_get_limit(
@@ -413,7 +601,7 @@ static int ext4_dir_dx_get_leaf(struct ext4_hash_info *hinfo,
 
                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;
 
@@ -430,6 +618,10 @@ static int ext4_dir_dx_get_leaf(struct ext4_hash_info *hinfo,
                    ext4_sb_get_block_size(&inode_ref->fs->sb) -
                    sizeof(struct ext4_fake_directory_entry);
 
+               if (ext4_sb_feature_ro_com(&inode_ref->fs->sb,
+                               EXT4_FRO_COM_METADATA_CSUM))
+                       entry_space -= sizeof(struct ext4_directory_dx_tail);
+
                entry_space =
                    entry_space / sizeof(struct ext4_directory_dx_entry);
 
@@ -438,6 +630,16 @@ static int ext4_dir_dx_get_leaf(struct ext4_hash_info *hinfo,
                        return EXT4_ERR_BAD_DX_DIR;
                }
 
+               if (!ext4_dir_dx_checksum_verify(inode_ref,
+                                       (struct ext4_directory_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;
        }
 
@@ -490,7 +692,7 @@ static int ext4_dir_dx_next_block(struct ext4_inode_ref *inode_ref,
                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 +701,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_directory_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,7 +718,7 @@ 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;
                p->position = p->entries;
@@ -523,7 +735,8 @@ int ext4_dir_dx_find_entry(struct ext4_directory_search_result *result,
        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 +747,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_directory_entry_ll *)root_block.data)) {
+               ext4_dbg(DEBUG_DIR_IDX,
+                        DBG_WARN "HTree root checksum failed."
+                        "Inode: %" PRIu32", "
+                        "Block: %" PRIu32"\n",
+                        inode_ref->index,
+                        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);
@@ -564,7 +787,8 @@ int ext4_dir_dx_find_entry(struct ext4_directory_search_result *result,
                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,6 +797,16 @@ 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_directory_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;
                rc = ext4_dir_find_in_block(&leaf_block, &fs->sb, name_len,
@@ -679,13 +913,15 @@ 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_directory_dx_block *index_block,
                         uint32_t hash, uint32_t iblock)
 {
        struct ext4_directory_dx_entry *old_index_entry = index_block->position;
@@ -706,6 +942,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_directory_entry_ll *)index_block->block.data);
        index_block->block.dirty = true;
 }
 
@@ -841,6 +1079,9 @@ 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_directory_entry_tail);
 
        /* First part - to the old block */
        for (i = 0; i < mid; ++i) {
@@ -875,14 +1116,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_directory_entry_ll *)old_data_block->data);
+       ext4_dir_set_checksum(inode_ref,
+                       (struct ext4_directory_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;
 
@@ -901,6 +1157,7 @@ ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
                        struct ext4_directory_dx_block *dx_block,
                        struct ext4_directory_dx_block **new_dx_block)
 {
+       struct ext4_sblock *sb = &inode_ref->fs->sb;
        struct ext4_directory_dx_entry *entries;
 
        if (dx_block == dx_blocks)
@@ -991,9 +1248,12 @@ ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
                        uint32_t entry_space =
                            block_size -
                            sizeof(struct ext4_fake_directory_entry);
+                       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM))
+                               entry_space -= sizeof(struct ext4_directory_dx_tail);
+
                        uint32_t node_limit =
-                           entry_space /
-                           sizeof(struct ext4_directory_dx_entry);
+                           entry_space / sizeof(struct ext4_directory_dx_entry);
+
                        ext4_dir_dx_countlimit_set_limit(right_countlimit,
                                                         node_limit);
 
@@ -1001,6 +1261,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_directory_entry_ll *)
+                                               dx_block->block.data);
                                dx_block->block.dirty = true;
 
                                struct ext4_block block_tmp = dx_block->block;
@@ -1015,11 +1279,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_directory_entry_ll *)
+                                                       dx_blocks[0].block.data);
+                       ext4_dir_set_dx_checksum(inode_ref,
+                                               (struct ext4_directory_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_directory_entry_ll *)
+                                                       new_block.data);
                        new_block.dirty = true;
                        return ext4_block_set(inode_ref->fs->bdev, &new_block);
                } else {
@@ -1036,9 +1310,11 @@ ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,
                        uint32_t entry_space =
                            block_size -
                            sizeof(struct ext4_fake_directory_entry);
+                       if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM))
+                               entry_space -= sizeof(struct ext4_directory_dx_tail);
+
                        uint32_t node_limit =
-                           entry_space /
-                           sizeof(struct ext4_directory_dx_entry);
+                           entry_space / sizeof(struct ext4_directory_dx_entry);
                        ext4_dir_dx_countlimit_set_limit(new_countlimit,
                                                         node_limit);
 
@@ -1064,6 +1340,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_directory_entry_ll *)
+                                                       dx_blocks[0].block.data);
+                       ext4_dir_set_dx_checksum(inode_ref,
+                                               (struct ext4_directory_entry_ll *)
+                                                       dx_blocks[1].block.data);
                        dx_blocks[0].block.dirty = true;
                        dx_blocks[1].block.dirty = true;
                }
@@ -1080,7 +1362,9 @@ int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent,
        /* Get direct block 0 (index root) */
        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 +1375,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_directory_entry_ll *)root_block.data)) {
+               ext4_dbg(DEBUG_DIR_IDX,
+                        DBG_WARN "HTree root checksum failed."
+                        "Inode: %" PRIu32", "
+                        "Block: %" PRIu32"\n",
+                        parent->index,
+                        0);
+       }
+
        /* Initialize hinfo structure (mainly compute hash) */
        uint32_t name_len = strlen(name);
        struct ext4_hash_info hinfo;
@@ -1120,7 +1414,8 @@ int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent,
            ext4_dir_dx_entry_get_block(dx_block->position);
        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,8 +1432,18 @@ 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_directory_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,
+       rc = ext4_dir_try_insert_entry(&fs->sb, parent, &target_block, child, name,
                                       name_len);
        if (rc == EOK)
                goto release_target_index;
@@ -1156,10 +1461,10 @@ 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,
+               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,
+               rc = ext4_dir_try_insert_entry(&fs->sb, parent, &target_block, child,
                                               name, name_len);
 
        /* Cleanup */
@@ -1198,7 +1503,7 @@ int ext4_dir_dx_reset_parent_inode(struct ext4_inode_ref *dir,
 {
        /* Load block 0, where will be index root located */
        ext4_fsblk_t fblock;
-       int rc = ext4_fs_get_inode_data_block_index(dir, 0, &fblock);
+       int rc = ext4_fs_get_inode_data_block_index(dir, 0, &fblock, false);
        if (rc != EOK)
                return rc;
 
@@ -1207,12 +1512,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_directory_entry_ll *)block.data)) {
+               ext4_dbg(DEBUG_DIR_IDX,
+                        DBG_WARN "HTree root checksum failed."
+                        "Inode: %" PRIu32", "
+                        "Block: %" PRIu32"\n",
+                        dir->index,
+                        0);
+       }
+
        /* Initialize pointers to data structures */
        struct ext4_directory_dx_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_directory_entry_ll *)
+                                       block.data);
        block.dirty = true;
 
        return ext4_block_set(dir->fs->bdev, &block);