X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=lwext4%2Fext4_dir_idx.c;h=e85d04cce5deaba0061abcf80607c8b6ff7c6edb;hb=ce4eae952d8a1eab8ebe3a168e7e3a791bab9607;hp=4782f8d9d2ceb1b7fd1e3525b93e80954e96ceda;hpb=bdb50541baac6e536b7201ccf35abe56816bec04;p=lwext4.git diff --git a/lwext4/ext4_dir_idx.c b/lwext4/ext4_dir_idx.c index 4782f8d..e85d04c 100644 --- a/lwext4/ext4_dir_idx.c +++ b/lwext4/ext4_dir_idx.c @@ -51,60 +51,61 @@ * @param root_info Pointer to root info structure of index * @return Hash algorithm version */ -static inline uint8_t ext4_dir_dx_root_info_get_hash_version( - struct ext4_dir_idx_root_info *root_info) +static inline uint8_t +ext4_dir_dx_rinfo_get_hash_version(struct ext4_dir_idx_rinfo *ri) { - return root_info->hash_version; + return ri->hash_version; } /**@brief Set hash version, that will be used in directory index. * @param root_info Pointer to root info structure of index * @param v Hash algorithm version */ -static inline void ext4_dir_dx_root_info_set_hash_version( - struct ext4_dir_idx_root_info *root_info, uint8_t v) +static inline void +ext4_dir_dx_rinfo_set_hash_version(struct ext4_dir_idx_rinfo *ri, uint8_t v) { - root_info->hash_version = v; + ri->hash_version = v; } /**@brief Get length of root_info structure in bytes. * @param root_info Pointer to root info structure of index * @return Length of the structure */ -static inline uint8_t ext4_dir_dx_root_info_get_info_length( - struct ext4_dir_idx_root_info *root_info) +static inline uint8_t +ext4_dir_dx_rinfo_get_info_length(struct ext4_dir_idx_rinfo *ri) { - return root_info->info_length; + return ri->info_length; } /**@brief Set length of root_info structure in bytes. * @param root_info Pointer to root info structure of index * @param info_length Length of the structure */ -static inline void ext4_dir_dx_root_info_set_info_length( - struct ext4_dir_idx_root_info *root_info, uint8_t len) +static inline void +ext4_dir_dx_root_info_set_info_length(struct ext4_dir_idx_rinfo *ri, + uint8_t len) { - root_info->info_length = len; + ri->info_length = len; } /**@brief Get number of indirect levels of HTree. * @param root_info Pointer to root info structure of index * @return Height of HTree (actually only 0 or 1) */ -static inline uint8_t ext4_dir_dx_root_info_get_indirect_levels( - struct ext4_dir_idx_root_info *root_info) +static inline uint8_t +ext4_dir_dx_rinfo_get_indirect_levels(struct ext4_dir_idx_rinfo *ri) { - return root_info->indirect_levels; + return ri->indirect_levels; } /**@brief Set number of indirect levels of HTree. * @param root_info Pointer to root info structure of index * @param lvl Height of HTree (actually only 0 or 1) */ -static inline void ext4_dir_dx_root_info_set_indirect_levels( - struct ext4_dir_idx_root_info *root_info, uint8_t lvl) +static inline void +ext4_dir_dx_rinfo_set_indirect_levels(struct ext4_dir_idx_rinfo *ri, uint8_t l) { - root_info->indirect_levels = lvl; + ri->indirect_levels = l; } /**@brief Get maximum number of index node entries. @@ -112,7 +113,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_dir_idx_countlimit *climit) +ext4_dir_dx_climit_get_limit(struct ext4_dir_idx_climit *climit) { return to_le16(climit->limit); } @@ -122,8 +123,7 @@ ext4_dir_dx_countlimit_get_limit(struct ext4_dir_idx_countlimit *climit) * @param limit Maximum of entries in node */ static inline void -ext4_dir_dx_countlimit_set_limit(struct ext4_dir_idx_countlimit *climit, - uint16_t limit) +ext4_dir_dx_climit_set_limit(struct ext4_dir_idx_climit *climit, uint16_t limit) { climit->limit = to_le16(limit); } @@ -133,7 +133,7 @@ ext4_dir_dx_countlimit_set_limit(struct ext4_dir_idx_countlimit *climit, * @return Number of entries in node */ static inline uint16_t -ext4_dir_dx_countlimit_get_count(struct ext4_dir_idx_countlimit *climit) +ext4_dir_dx_climit_get_count(struct ext4_dir_idx_climit *climit) { return to_le16(climit->count); } @@ -143,8 +143,7 @@ ext4_dir_dx_countlimit_get_count(struct ext4_dir_idx_countlimit *climit) * @param count Number of entries in node */ static inline void -ext4_dir_dx_countlimit_set_count(struct ext4_dir_idx_countlimit *climit, - uint16_t count) +ext4_dir_dx_climit_set_count(struct ext4_dir_idx_climit *climit, uint16_t count) { climit->count = to_le16(count); } @@ -184,8 +183,7 @@ ext4_dir_dx_entry_get_block(struct ext4_dir_idx_entry *entry) * @param block Block address of child node */ static inline void -ext4_dir_dx_entry_set_block(struct ext4_dir_idx_entry *entry, - uint32_t block) +ext4_dir_dx_entry_set_block(struct ext4_dir_idx_entry *entry, uint32_t block) { entry->block = to_le32(block); } @@ -205,147 +203,139 @@ static int ext4_dir_dx_hash_string(struct ext4_hash_info *hinfo, int len, } #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) +static uint32_t ext4_dir_dx_checksum(struct ext4_inode_ref *inode_ref, void *de, + int count_offset, int count, + struct ext4_dir_idx_tail *t) { - uint32_t orig_checksum, checksum = 0; + uint32_t orig_cum, csum = 0; struct ext4_sblock *sb = &inode_ref->fs->sb; - int size; + int sz; /* 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)); + uint32_t ino_gen; + 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; + sz = count_offset + (count * sizeof(struct ext4_dir_idx_tail)); + orig_cum = t->checksum; t->checksum = 0; /* First calculate crc32 checksum against fs uuid */ - checksum = ext4_crc32c(EXT4_CRC32_INIT, sb->uuid, - sizeof(sb->uuid)); + csum = 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)); + csum = ext4_crc32c(csum, &ino_index, sizeof(ino_index)); + csum = ext4_crc32c(csum, &ino_gen, sizeof(ino_gen)); /* After that calculate crc32 checksum against all the dx_entry */ - checksum = ext4_crc32c(checksum, dirent, size); + csum = ext4_crc32c(csum, de, sz); /* Finally calculate crc32 checksum for dx_tail */ - checksum = ext4_crc32c(checksum, t, - sizeof(struct ext4_dir_idx_tail)); - t->checksum = orig_checksum; + csum = ext4_crc32c(csum, t, sizeof(struct ext4_dir_idx_tail)); + t->checksum = orig_cum; } - return checksum; + return csum; } -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) +static struct ext4_dir_idx_climit * +ext4_dir_dx_get_climit(struct ext4_inode_ref *inode_ref, + struct ext4_dir_en *dirent, int *offset) { - struct ext4_dir_entry_ll *dp; + struct ext4_dir_en *dp; struct ext4_dir_idx_root *root; struct ext4_sblock *sb = &inode_ref->fs->sb; + uint32_t block_size = ext4_sb_get_block_size(sb); + uint16_t entry_len = ext4_dir_en_get_entry_len(dirent); 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) { + + if (entry_len == 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) + dp = (struct ext4_dir_en *)&root->dots[1]; + if (ext4_dir_en_get_entry_len(dp) != (block_size - 12)) return NULL; - if (root->info.reserved_zero || - root->info.info_length != sizeof(struct ext4_dir_idx_root_info)) + if (root->info.reserved_zero) + return NULL; + if (root->info.info_length != sizeof(struct ext4_dir_idx_rinfo)) return NULL; count_offset = 32; - } else + } else if (entry_len == block_size) { + count_offset = 8; + } else { return NULL; + } if (offset) *offset = count_offset; - return (struct ext4_dir_idx_countlimit *)(((char *)dirent) + count_offset); + return (struct ext4_dir_idx_climit *)(((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) +static bool ext4_dir_dx_csum_verify(struct ext4_inode_ref *inode_ref, + struct ext4_dir_en *de) { struct ext4_sblock *sb = &inode_ref->fs->sb; - int count_offset, limit, count; + uint32_t block_size = ext4_sb_get_block_size(sb); + int coff, limit, cnt; 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) { + struct ext4_dir_idx_climit *climit; + climit = ext4_dir_dx_get_climit(inode_ref, de, &coff); + if (!climit) { /* 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)) { + limit = ext4_dir_dx_climit_get_limit(climit); + cnt = ext4_dir_dx_climit_get_count(climit); + if (coff + (limit * sizeof(struct ext4_dir_idx_entry)) > + (block_size - 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); + t = (void *)(((struct ext4_dir_idx_entry *)climit) + limit); - if (t->checksum != to_le32(ext4_dir_dx_checksum(inode_ref, - dirent, - count_offset, - count, t))) + uint32_t c; + c = to_le32(ext4_dir_dx_checksum(inode_ref, de, coff, cnt, t)); + if (t->checksum != c) return false; } return true; } -static void -ext4_dir_set_dx_checksum(struct ext4_inode_ref *inode_ref, - struct ext4_dir_entry_ll *dirent) +static void ext4_dir_set_dx_csum(struct ext4_inode_ref *inode_ref, + struct ext4_dir_en *dirent) { - int count_offset, limit, count; + int coff, limit, count; struct ext4_sblock *sb = &inode_ref->fs->sb; + uint32_t block_size = ext4_sb_get_block_size(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) { + struct ext4_dir_idx_climit *climit; + climit = ext4_dir_dx_get_climit(inode_ref, dirent, &coff); + if (!climit) { /* 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)) { + limit = ext4_dir_dx_climit_get_limit(climit); + count = ext4_dir_dx_climit_get_count(climit); + if (coff + (limit * sizeof(struct ext4_dir_idx_entry)) > + (block_size - 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 = (void *)(((struct ext4_dir_idx_entry *)climit) + limit); t->checksum = to_le32(ext4_dir_dx_checksum(inode_ref, dirent, - count_offset, count, t)); + coff, count, t)); } } #else -#define ext4_dir_dx_checksum_verify(...) true -#define ext4_dir_set_dx_checksum(...) +#define ext4_dir_dx_csum_verify(...) true +#define ext4_dir_set_dx_csum(...) #endif /****************************************************************************/ @@ -356,6 +346,8 @@ int ext4_dir_dx_init(struct ext4_inode_ref *dir, struct ext4_inode_ref *parent) ext4_fsblk_t fblock; uint32_t iblock; struct ext4_sblock *sb = &dir->fs->sb; + uint32_t block_size = ext4_sb_get_block_size(&dir->fs->sb); + int rc = ext4_fs_append_inode_block(dir, &fblock, &iblock); if (rc != EOK) return rc; @@ -367,49 +359,41 @@ int ext4_dir_dx_init(struct ext4_inode_ref *dir, struct ext4_inode_ref *parent) /* Initialize pointers to data structures */ struct ext4_dir_idx_root *root = (void *)block.data; - struct ext4_dir_idx_root_info *info = &(root->info); + struct ext4_dir_idx_rinfo *info = &(root->info); memset(root, 0, sizeof(struct ext4_dir_idx_root)); + struct ext4_dir_en *de; /* 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("..")); + de = (struct ext4_dir_en *)root->dots; + ext4_dir_write_entry(sb, de, 12, dir, ".", strlen(".")); + + de = (struct ext4_dir_en *)(root->dots + 1); + uint16_t elen = block_size - 12; + ext4_dir_write_entry(sb, de, elen, parent, "..", strlen("..")); /* Initialize root info structure */ uint8_t hash_version = ext4_get8(&dir->fs->sb, default_hash_version); - ext4_dir_dx_root_info_set_hash_version(info, hash_version); - ext4_dir_dx_root_info_set_indirect_levels(info, 0); + ext4_dir_dx_rinfo_set_hash_version(info, hash_version); + ext4_dir_dx_rinfo_set_indirect_levels(info, 0); ext4_dir_dx_root_info_set_info_length(info, 8); /* Set limit and current number of entries */ - struct ext4_dir_idx_countlimit *countlimit = - (struct ext4_dir_idx_countlimit *)&root->entries; + struct ext4_dir_idx_climit *climit; + climit = (struct ext4_dir_idx_climit *)&root->en; - ext4_dir_dx_countlimit_set_count(countlimit, 1); + ext4_dir_dx_climit_set_count(climit, 1); + + uint32_t entry_space; + entry_space = block_size - 2 * sizeof(struct ext4_dir_idx_dot_en) - + sizeof(struct ext4_dir_idx_rinfo); - uint32_t block_size = ext4_sb_get_block_size(&dir->fs->sb); - uint32_t entry_space = block_size - - 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_dir_idx_entry); - - ext4_dir_dx_countlimit_set_limit(countlimit, root_limit); + uint16_t root_limit = entry_space / sizeof(struct ext4_dir_idx_entry); + ext4_dir_dx_climit_set_limit(climit, root_limit); /* Append new block, where will be new entries inserted in the future */ rc = ext4_fs_append_inode_block(dir, &fblock, &iblock); @@ -419,7 +403,6 @@ int ext4_dir_dx_init(struct ext4_inode_ref *dir, struct ext4_inode_ref *parent) } struct ext4_block new_block; - rc = ext4_block_get_noread(dir->fs->bdev, &new_block, fblock); if (rc != EOK) { ext4_block_set(dir->fs->bdev, &block); @@ -427,25 +410,20 @@ int ext4_dir_dx_init(struct ext4_inode_ref *dir, struct ext4_inode_ref *parent) } /* Fill the whole block with empty entry */ - struct ext4_dir_entry_ll *block_entry = (void *)new_block.data; + struct ext4_dir_en *be = (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); + uint16_t len = block_size - sizeof(struct ext4_dir_entry_tail); + ext4_dir_en_set_entry_len(be, len); + ext4_dir_en_set_name_len(sb, be, 0); + ext4_dir_en_set_inode_type(sb, be, EXT4_DE_UNKNOWN); + ext4_dir_init_entry_tail(EXT4_DIRENT_TAIL(be, block_size)); + ext4_dir_set_csum(dir, be); } else { - ext4_dir_entry_ll_set_entry_length(block_entry, block_size); + ext4_dir_en_set_entry_len(be, block_size); } - ext4_dir_entry_ll_set_inode(block_entry, 0); + ext4_dir_en_set_inode(be, 0); new_block.dirty = true; rc = ext4_block_set(dir->fs->bdev, &new_block); @@ -455,10 +433,10 @@ int ext4_dir_dx_init(struct ext4_inode_ref *dir, struct ext4_inode_ref *parent) } /* Connect new block to the only entry in index */ - struct ext4_dir_idx_entry *entry = root->entries; + struct ext4_dir_idx_entry *entry = root->en; ext4_dir_dx_entry_set_block(entry, iblock); - ext4_dir_set_dx_checksum(dir, (struct ext4_dir_entry_ll *)block.data); + ext4_dir_set_dx_csum(dir, (struct ext4_dir_en *)block.data); block.dirty = true; return ext4_block_set(dir->fs->bdev, &block); @@ -477,9 +455,9 @@ static int ext4_dir_hinfo_init(struct ext4_hash_info *hinfo, struct ext4_sblock *sb, size_t name_len, const char *name) { - struct ext4_dir_idx_root *root = - (struct ext4_dir_idx_root *)root_block->data; + struct ext4_dir_idx_root *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) && (root->info.hash_version != EXT2_HTREE_TEA)) @@ -496,20 +474,19 @@ 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_dir_idx_dot_entry); - entry_space -= sizeof(struct ext4_dir_idx_root_info); + entry_space -= 2 * sizeof(struct ext4_dir_idx_dot_en); + entry_space -= sizeof(struct ext4_dir_idx_rinfo); 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_dir_idx_countlimit *)&root->entries); + struct ext4_dir_idx_climit *climit = (void *)&root->en; + uint16_t limit = ext4_dir_dx_climit_get_limit(climit); if (limit != entry_space) return EXT4_ERR_BAD_DX_DIR; /* Check hash version and modify if necessary */ - hinfo->hash_version = - ext4_dir_dx_root_info_get_hash_version(&root->info); + hinfo->hash_version = ext4_dir_dx_rinfo_get_hash_version(&root->info); if ((hinfo->hash_version <= EXT2_HTREE_TEA) && (ext4_sb_check_flag(sb, EXT4_SUPERBLOCK_FLAGS_UNSIGNED_HASH))) { /* Use unsigned hash */ @@ -517,7 +494,6 @@ static int ext4_dir_hinfo_init(struct ext4_hash_info *hinfo, } /* Load hash seed from superblock */ - hinfo->seed = ext4_get8(sb, hash_seed); /* Compute hash value of name */ @@ -541,33 +517,38 @@ static int ext4_dir_dx_get_leaf(struct ext4_hash_info *hinfo, struct ext4_dir_idx_block **dx_block, struct ext4_dir_idx_block *dx_blocks) { - 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_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_dir_idx_root *root; + struct ext4_dir_idx_entry *entries; struct ext4_dir_idx_entry *p; struct ext4_dir_idx_entry *q; struct ext4_dir_idx_entry *m; struct ext4_dir_idx_entry *at; + ext4_fsblk_t fblock; + uint32_t block_size; + uint16_t limit; + uint16_t entry_space; + uint8_t ind_level; + int r; + + struct ext4_dir_idx_block *tmp_dx_blk = dx_blocks; + struct ext4_block *tmp_blk = root_block; + struct ext4_sblock *sb = &inode_ref->fs->sb; + + block_size = ext4_sb_get_block_size(sb); + root = (struct ext4_dir_idx_root *)root_block->data; + entries = (struct ext4_dir_idx_entry *)&root->en; + limit = ext4_dir_dx_climit_get_limit((void *)entries); + ind_level = ext4_dir_dx_rinfo_get_indirect_levels(&root->info); /* Walk through the index tree */ while (true) { - uint16_t count = ext4_dir_dx_countlimit_get_count( - (struct ext4_dir_idx_countlimit *)entries); - if ((count == 0) || (count > limit)) + uint16_t cnt = ext4_dir_dx_climit_get_count((void *)entries); + if ((cnt == 0) || (cnt > limit)) return EXT4_ERR_BAD_DX_DIR; /* Do binary search in every node */ p = entries + 1; - q = entries + count - 1; + q = entries + cnt - 1; while (p <= q) { m = p + (q - p) / 2; @@ -580,54 +561,45 @@ static int ext4_dir_dx_get_leaf(struct ext4_hash_info *hinfo, at = p - 1; /* Write results */ - - memcpy(&tmp_dx_block->block, tmp_block, - sizeof(struct ext4_block)); - tmp_dx_block->entries = entries; - tmp_dx_block->position = at; + memcpy(&tmp_dx_blk->b, tmp_blk, sizeof(struct ext4_block)); + tmp_dx_blk->entries = entries; + tmp_dx_blk->position = at; /* Is algorithm in the leaf? */ - if (indirect_level == 0) { - *dx_block = tmp_dx_block; + if (ind_level == 0) { + *dx_block = tmp_dx_blk; return EOK; } /* Goto child node */ uint32_t next_block = ext4_dir_dx_entry_get_block(at); - indirect_level--; + ind_level--; - ext4_fsblk_t fblock; - int rc = ext4_fs_get_inode_data_block_index( - inode_ref, next_block, &fblock, false); - if (rc != EOK) - return rc; + r = ext4_fs_get_inode_data_block_index(inode_ref, next_block, + &fblock, false); + if (r != EOK) + return r; - rc = ext4_block_get(inode_ref->fs->bdev, tmp_block, fblock); - if (rc != EOK) - return rc; - - entries = - ((struct ext4_dir_idx_node *)tmp_block->data)->entries; - limit = ext4_dir_dx_countlimit_get_limit( - (struct ext4_dir_idx_countlimit *)entries); + r = ext4_block_get(inode_ref->fs->bdev, tmp_blk, fblock); + if (r != EOK) + return r; - struct ext4_sblock *sb = &inode_ref->fs->sb; - uint16_t entry_space = ext4_sb_get_block_size(sb) - - sizeof(struct ext4_fake_dir_entry); + entries = ((struct ext4_dir_idx_node *)tmp_blk->data)->entries; + limit = ext4_dir_dx_climit_get_limit((void *)entries); + entry_space = block_size - 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); entry_space = entry_space / sizeof(struct ext4_dir_idx_entry); if (limit != entry_space) { - ext4_block_set(inode_ref->fs->bdev, tmp_block); + ext4_block_set(inode_ref->fs->bdev, tmp_blk); return EXT4_ERR_BAD_DX_DIR; } - if (!ext4_dir_dx_checksum_verify(inode_ref, - (struct ext4_dir_entry_ll *)tmp_block->data)) { + if (!ext4_dir_dx_csum_verify(inode_ref, (void *)tmp_blk->data)) { ext4_dbg(DEBUG_DIR_IDX, DBG_WARN "HTree checksum failed." "Inode: %" PRIu32", " @@ -636,7 +608,7 @@ static int ext4_dir_dx_get_leaf(struct ext4_hash_info *hinfo, next_block); } - ++tmp_dx_block; + ++tmp_dx_blk; } /* Unreachable */ @@ -655,16 +627,17 @@ static int ext4_dir_dx_next_block(struct ext4_inode_ref *inode_ref, struct ext4_dir_idx_block *dx_block, struct ext4_dir_idx_block *dx_blocks) { + int r; uint32_t num_handles = 0; + ext4_fsblk_t block_addr; 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_dir_idx_countlimit *)p->entries); + uint16_t cnt = ext4_dir_dx_climit_get_count((void *)p->entries); - if (p->position < p->entries + count) + p->position++; + if (p->position < p->entries + cnt) break; if (p == dx_blocks) @@ -685,20 +658,18 @@ 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); - ext4_fsblk_t block_addr; - int rc = ext4_fs_get_inode_data_block_index( - inode_ref, block_idx, &block_addr, false); - if (rc != EOK) - return rc; + r = ext4_fs_get_inode_data_block_index(inode_ref, block_idx, + &block_addr, false); + if (r != EOK) + return r; - struct ext4_block block; - rc = ext4_block_get(inode_ref->fs->bdev, &block, block_addr); - if (rc != EOK) - return rc; + struct ext4_block b; + r = ext4_block_get(inode_ref->fs->bdev, &b, block_addr); + if (r != EOK) + return r; - if (!ext4_dir_dx_checksum_verify(inode_ref, - (struct ext4_dir_entry_ll *)block.data)) { + if (!ext4_dir_dx_csum_verify(inode_ref, (void *)b.data)) { ext4_dbg(DEBUG_DIR_IDX, DBG_WARN "HTree checksum failed." "Inode: %" PRIu32", " @@ -710,13 +681,12 @@ static int ext4_dir_dx_next_block(struct ext4_inode_ref *inode_ref, p++; /* Don't forget to put old block (prevent memory leak) */ - rc = ext4_block_set(inode_ref->fs->bdev, &p->block); - if (rc != EOK) - return rc; + r = ext4_block_set(inode_ref->fs->bdev, &p->b); + if (r != EOK) + return r; - memcpy(&p->block, &block, sizeof(block)); - p->entries = - ((struct ext4_dir_idx_node *)block.data)->entries; + memcpy(&p->b, &b, sizeof(b)); + p->entries = ((struct ext4_dir_idx_node *)b.data)->entries; p->position = p->entries; } @@ -730,9 +700,9 @@ int ext4_dir_dx_find_entry(struct ext4_dir_search_result *result, /* Load direct block 0 (index root) */ ext4_fsblk_t root_block_addr; int rc2; - int rc = - ext4_fs_get_inode_data_block_index(inode_ref, - 0, &root_block_addr, false); + int rc; + rc = ext4_fs_get_inode_data_block_index(inode_ref, 0, &root_block_addr, + false); if (rc != EOK) return rc; @@ -743,8 +713,7 @@ int ext4_dir_dx_find_entry(struct ext4_dir_search_result *result, if (rc != EOK) return rc; - if (!ext4_dir_dx_checksum_verify(inode_ref, - (struct ext4_dir_entry_ll *)root_block.data)) { + if (!ext4_dir_dx_csum_verify(inode_ref, (void *)root_block.data)) { ext4_dbg(DEBUG_DIR_IDX, DBG_WARN "HTree root checksum failed." "Inode: %" PRIu32", " @@ -778,45 +747,42 @@ int ext4_dir_dx_find_entry(struct ext4_dir_search_result *result, do { /* Load leaf block */ - uint32_t leaf_block_idx = - ext4_dir_dx_entry_get_block(dx_block->position); + uint32_t leaf_blk_idx; ext4_fsblk_t leaf_block_addr; + struct ext4_block b; - rc = ext4_fs_get_inode_data_block_index( - inode_ref, leaf_block_idx, &leaf_block_addr, - false); + leaf_blk_idx = ext4_dir_dx_entry_get_block(dx_block->position); + rc = ext4_fs_get_inode_data_block_index(inode_ref, leaf_blk_idx, + &leaf_block_addr, false); if (rc != EOK) goto cleanup; - struct ext4_block leaf_block; - rc = ext4_block_get(fs->bdev, &leaf_block, leaf_block_addr); + rc = ext4_block_get(fs->bdev, &b, leaf_block_addr); if (rc != EOK) goto cleanup; - if (!ext4_dir_checksum_verify(inode_ref, - (struct ext4_dir_entry_ll *)leaf_block.data)) { + if (!ext4_dir_csum_verify(inode_ref, (void *)b.data)) { ext4_dbg(DEBUG_DIR_IDX, DBG_WARN "HTree leaf block checksum failed." "Inode: %" PRIu32", " "Block: %" PRIu32"\n", inode_ref->index, - leaf_block_idx); + leaf_blk_idx); } /* Linear search inside block */ - struct ext4_dir_entry_ll *res_dentry; - rc = ext4_dir_find_in_block(&leaf_block, &fs->sb, name_len, - name, &res_dentry); + struct ext4_dir_en *de; + rc = ext4_dir_find_in_block(&b, &fs->sb, name_len, name, &de); /* Found => return it */ if (rc == EOK) { - result->block = leaf_block; - result->dentry = res_dentry; + result->block = b; + result->dentry = de; goto cleanup; } /* Not found, leave untouched */ - rc2 = ext4_block_set(fs->bdev, &leaf_block); + rc2 = ext4_block_set(fs->bdev, &b); if (rc2 != EOK) goto cleanup; @@ -838,7 +804,7 @@ cleanup: tmp = dx_blocks; while (tmp <= dx_block) { - rc2 = ext4_block_set(fs->bdev, &tmp->block); + rc2 = ext4_block_set(fs->bdev, &tmp->b); if (rc == EOK && rc2 != EOK) rc = rc2; ++tmp; @@ -922,25 +888,20 @@ ext4_dir_dx_insert_entry(struct ext4_inode_ref *inode_ref __unused, { 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_dir_idx_countlimit *countlimit = - (struct ext4_dir_idx_countlimit *)index_block->entries; - uint32_t count = ext4_dir_dx_countlimit_get_count(countlimit); - + struct ext4_dir_idx_climit *climit = (void *)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); + uint32_t count = ext4_dir_dx_climit_get_count(climit); + + size_t bytes; + bytes = (uint8_t *)(start_index + count) - (uint8_t *)(new_index_entry); memmove(new_index_entry + 1, new_index_entry, bytes); ext4_dir_dx_entry_set_block(new_index_entry, iblock); ext4_dir_dx_entry_set_hash(new_index_entry, hash); - - 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; + ext4_dir_dx_climit_set_count(climit, count + 1); + ext4_dir_set_dx_csum(inode_ref, (void *)index_block->b.data); + index_block->b.dirty = true; } /**@brief Split directory entries to two parts preventing node overflow. @@ -957,23 +918,22 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref, struct ext4_block *new_data_block) { int rc = EOK; - - /* Allocate buffer for directory entries */ + struct ext4_sblock *sb = &inode_ref->fs->sb; uint32_t block_size = ext4_sb_get_block_size(&inode_ref->fs->sb); + /* Allocate buffer for directory entries */ uint8_t *entry_buffer = malloc(block_size); if (entry_buffer == NULL) return ENOMEM; /* dot entry has the smallest size available */ - uint32_t max_entry_count = - block_size / sizeof(struct ext4_dir_idx_dot_entry); + uint32_t max_ecnt = block_size / sizeof(struct ext4_dir_idx_dot_en); /* Allocate sort entry */ - struct ext4_dx_sort_entry *sort_array = - malloc(max_entry_count * sizeof(struct ext4_dx_sort_entry)); + struct ext4_dx_sort_entry *sort; - if (sort_array == NULL) { + sort = malloc(max_ecnt * sizeof(struct ext4_dx_sort_entry)); + if (sort == NULL) { free(entry_buffer); return ENOMEM; } @@ -982,51 +942,48 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref, uint32_t real_size = 0; /* Initialize hinfo */ - struct ext4_hash_info tmp_hinfo; - memcpy(&tmp_hinfo, hinfo, sizeof(struct ext4_hash_info)); + struct ext4_hash_info hinfo_tmp; + memcpy(&hinfo_tmp, hinfo, sizeof(struct ext4_hash_info)); /* Load all valid entries to the buffer */ - struct ext4_dir_entry_ll *dentry = (void *)old_data_block->data; + struct ext4_dir_en *de = (void *)old_data_block->data; uint8_t *entry_buffer_ptr = entry_buffer; - while ((void *)dentry < (void *)(old_data_block->data + block_size)) { + while ((void *)de < (void *)(old_data_block->data + block_size)) { /* Read only valid entries */ - 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); - - rc = ext4_dir_dx_hash_string(&tmp_hinfo, len, - (char *)dentry->name); + if (ext4_dir_en_get_inode(de) && de->name_len) { + uint8_t len = ext4_dir_en_get_name_len(sb, de); + rc = ext4_dir_dx_hash_string(&hinfo_tmp, len, + (char *)de->name); if (rc != EOK) { - free(sort_array); + free(sort); free(entry_buffer); return rc; } uint32_t rec_len = 8 + len; - if ((rec_len % 4) != 0) rec_len += 4 - (rec_len % 4); - memcpy(entry_buffer_ptr, dentry, rec_len); + memcpy(entry_buffer_ptr, de, rec_len); - sort_array[idx].dentry = entry_buffer_ptr; - sort_array[idx].rec_len = rec_len; - sort_array[idx].hash = tmp_hinfo.hash; + sort[idx].dentry = entry_buffer_ptr; + sort[idx].rec_len = rec_len; + sort[idx].hash = hinfo_tmp.hash; entry_buffer_ptr += rec_len; real_size += rec_len; idx++; } - dentry = (void *)((uint8_t *)dentry + - ext4_dir_entry_ll_get_entry_length(dentry)); + size_t elen = ext4_dir_en_get_entry_len(de); + de = (void *)((uint8_t *)de + elen); } /* Sort all entries */ #if CONFIG_DIR_INDEX_COMB_SORT - comb_sort(sort_array, idx); + comb_sort(sort, idx); #else - qsort(sort_array, idx, sizeof(struct ext4_dx_sort_entry), + qsort(sort, idx, sizeof(struct ext4_dx_sort_entry), ext4_dir_dx_entry_comparator); #endif /* Allocate new block for store the second part of entries */ @@ -1034,7 +991,7 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref, uint32_t new_iblock; rc = ext4_fs_append_inode_block(inode_ref, &new_fblock, &new_iblock); if (rc != EOK) { - free(sort_array); + free(sort); free(entry_buffer); return rc; } @@ -1044,7 +1001,7 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref, rc = ext4_block_get_noread(inode_ref->fs->bdev, &new_data_block_tmp, new_fblock); if (rc != EOK) { - free(sort_array); + free(sort); free(entry_buffer); return rc; } @@ -1058,57 +1015,52 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref, uint32_t mid = 0; uint32_t i; for (i = 0; i < idx; ++i) { - if ((current_size + sort_array[i].rec_len) > (block_size / 2)) { - new_hash = sort_array[i].hash; + if ((current_size + sort[i].rec_len) > (block_size / 2)) { + new_hash = sort[i].hash; mid = i; break; } - current_size += sort_array[i].rec_len; + current_size += sort[i].rec_len; } /* Check hash collision */ uint32_t continued = 0; - if (new_hash == sort_array[mid - 1].hash) + if (new_hash == sort[mid - 1].hash) continued = 1; - uint32_t offset = 0; + uint32_t off = 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); + ptr = old_data_block->data + off; + memcpy(ptr, sort[i].dentry, sort[i].rec_len); - struct ext4_dir_entry_ll *tmp = ptr; + struct ext4_dir_en *t = ptr; if (i < (mid - 1)) - ext4_dir_entry_ll_set_entry_length( - tmp, sort_array[i].rec_len); + ext4_dir_en_set_entry_len(t, sort[i].rec_len); else - ext4_dir_entry_ll_set_entry_length(tmp, - block_size - offset); + ext4_dir_en_set_entry_len(t, block_size - off); - offset += sort_array[i].rec_len; + off += sort[i].rec_len; } /* Second part - to the new block */ - offset = 0; + off = 0; for (i = mid; i < idx; ++i) { - ptr = new_data_block_tmp.data + offset; - memcpy(ptr, sort_array[i].dentry, sort_array[i].rec_len); + ptr = new_data_block_tmp.data + off; + memcpy(ptr, sort[i].dentry, sort[i].rec_len); - struct ext4_dir_entry_ll *tmp = ptr; + struct ext4_dir_en *t = ptr; if (i < (idx - 1)) - ext4_dir_entry_ll_set_entry_length( - tmp, sort_array[i].rec_len); + ext4_dir_en_set_entry_len(t, sort[i].rec_len); else - ext4_dir_entry_ll_set_entry_length(tmp, - block_size - offset); + ext4_dir_en_set_entry_len(t, block_size - off); - offset += sort_array[i].rec_len; + off += sort[i].rec_len; } block_size = ext4_sb_get_block_size(&inode_ref->fs->sb); @@ -1116,27 +1068,25 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref, /* 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)); + struct ext4_dir_entry_tail *t; + + t = EXT4_DIRENT_TAIL(old_data_block->data, block_size); + ext4_dir_init_entry_tail(t); + t = EXT4_DIRENT_TAIL(new_data_block_tmp.data, block_size); + ext4_dir_init_entry_tail(t); } - 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); + ext4_dir_set_csum(inode_ref, (void *)old_data_block->data); + ext4_dir_set_csum(inode_ref, (void *)new_data_block_tmp.data); old_data_block->dirty = true; new_data_block_tmp.dirty = true; - free(sort_array); + free(sort); free(entry_buffer); - ext4_dir_dx_insert_entry(inode_ref, - 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; - return EOK; } @@ -1147,203 +1097,156 @@ static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref, * @return Error code */ static int -ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref, - struct ext4_dir_idx_block *dx_blocks, - struct ext4_dir_idx_block *dx_block, +ext4_dir_dx_split_index(struct ext4_inode_ref *ino_ref, + struct ext4_dir_idx_block *dx_blks, + struct ext4_dir_idx_block *dxb, struct ext4_dir_idx_block **new_dx_block) { - struct ext4_sblock *sb = &inode_ref->fs->sb; - struct ext4_dir_idx_entry *entries; + struct ext4_sblock *sb = &ino_ref->fs->sb; + struct ext4_dir_idx_entry *e; + int r; + + uint32_t block_size = ext4_sb_get_block_size(&ino_ref->fs->sb); + uint32_t entry_space = block_size - sizeof(struct ext4_fake_dir_entry); + uint32_t node_limit = entry_space / sizeof(struct ext4_dir_idx_entry); + + bool meta_csum = ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM); - if (dx_block == dx_blocks) - entries = - ((struct ext4_dir_idx_root *)dx_block->block.data) - ->entries; + if (dxb == dx_blks) + e = ((struct ext4_dir_idx_root *)dxb->b.data)->en; else - entries = - ((struct ext4_dir_idx_node *)dx_block->block.data) - ->entries; + e = ((struct ext4_dir_idx_node *)dxb->b.data)->entries; - struct ext4_dir_idx_countlimit *countlimit = - (struct ext4_dir_idx_countlimit *)entries; + struct ext4_dir_idx_climit *climit = (struct ext4_dir_idx_climit *)e; - uint16_t leaf_limit = ext4_dir_dx_countlimit_get_limit(countlimit); - uint16_t leaf_count = ext4_dir_dx_countlimit_get_count(countlimit); + uint16_t leaf_limit = ext4_dir_dx_climit_get_limit(climit); + uint16_t leaf_count = ext4_dir_dx_climit_get_count(climit); /* Check if is necessary to split index block */ if (leaf_limit == leaf_count) { - size_t levels = dx_block - dx_blocks; + struct ext4_dir_idx_entry *ren; + ptrdiff_t levels = dxb - dx_blks; - struct ext4_dir_idx_entry *root_entries = - ((struct ext4_dir_idx_root *)dx_blocks[0].block.data) - ->entries; + ren = ((struct ext4_dir_idx_root *)dx_blks[0].b.data)->en; + struct ext4_dir_idx_climit *rclimit = (void *)ren; + uint16_t root_limit = ext4_dir_dx_climit_get_limit(rclimit); + uint16_t root_count = ext4_dir_dx_climit_get_count(rclimit); - 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 = - ext4_dir_dx_countlimit_get_count(root_countlimit); /* Linux limitation */ if ((levels > 0) && (root_limit == root_count)) return ENOSPC; /* Add new block to directory */ - ext4_fsblk_t new_fblock; - uint32_t new_iblock; - int rc = ext4_fs_append_inode_block(inode_ref, &new_fblock, - &new_iblock); - if (rc != EOK) - return rc; + ext4_fsblk_t new_fblk; + uint32_t new_iblk; + r = ext4_fs_append_inode_block(ino_ref, &new_fblk, &new_iblk); + if (r != EOK) + return r; /* load new block */ - struct ext4_block new_block; - rc = - ext4_block_get_noread(inode_ref->fs->bdev, - &new_block, new_fblock); - if (rc != EOK) - return rc; + struct ext4_block b; + r = ext4_block_get_noread(ino_ref->fs->bdev, &b, new_fblk); + if (r != EOK) + return r; - struct ext4_dir_idx_node *new_node = - (void *)new_block.data; - struct ext4_dir_idx_entry *new_entries = new_node->entries; - - memset(&new_node->fake, 0, - sizeof(struct ext4_fake_dir_entry)); - - uint32_t block_size = - ext4_sb_get_block_size(&inode_ref->fs->sb); + struct ext4_dir_idx_node *new_node = (void *)b.data; + struct ext4_dir_idx_entry *new_en = new_node->entries; + memset(&new_node->fake, 0, sizeof(struct ext4_fake_dir_entry)); new_node->fake.entry_length = block_size; /* Split leaf node */ if (levels > 0) { uint32_t count_left = leaf_count / 2; uint32_t count_right = leaf_count - count_left; - uint32_t hash_right = - ext4_dir_dx_entry_get_hash(entries + count_left); + uint32_t hash_right; + size_t sz; + + struct ext4_dir_idx_climit *left_climit; + struct ext4_dir_idx_climit *right_climit; + hash_right = ext4_dir_dx_entry_get_hash(e + count_left); /* Copy data to new node */ - memcpy((void *)new_entries, - (void *)(entries + count_left), - count_right * - sizeof(struct ext4_dir_idx_entry)); + sz = count_right * sizeof(struct ext4_dir_idx_entry); + memcpy(new_en, e + count_left, sz); /* Initialize new node */ - 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); - ext4_dir_dx_countlimit_set_count(right_countlimit, - count_right); - - uint32_t entry_space = - block_size - - 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); + left_climit = (struct ext4_dir_idx_climit *)e; + right_climit = (struct ext4_dir_idx_climit *)new_en; + + ext4_dir_dx_climit_set_count(left_climit, count_left); + ext4_dir_dx_climit_set_count(right_climit, count_right); - uint32_t node_limit = - entry_space / sizeof(struct ext4_dir_idx_entry); + if (meta_csum) + entry_space -= sizeof(struct ext4_dir_idx_tail); - ext4_dir_dx_countlimit_set_limit(right_countlimit, - node_limit); + ext4_dir_dx_climit_set_limit(right_climit, node_limit); /* Which index block is target for new entry */ uint32_t position_index = - (dx_block->position - dx_block->entries); + (dxb->position - dxb->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; + ext4_dir_set_dx_csum( + ino_ref, + (struct ext4_dir_en *) + dxb->b.data); + dxb->b.dirty = true; - struct ext4_block block_tmp = dx_block->block; + struct ext4_block block_tmp = dxb->b; - dx_block->block = new_block; + dxb->b = b; - dx_block->position = - new_entries + position_index - count_left; - dx_block->entries = new_entries; + dxb->position = + new_en + position_index - count_left; + dxb->entries = new_en; - new_block = block_tmp; + b = block_tmp; } /* Finally insert new entry */ - 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); + ext4_dir_dx_insert_entry(ino_ref, dx_blks, hash_right, + new_iblk); + ext4_dir_set_dx_csum(ino_ref, (void *)dx_blks[0].b.data); + ext4_dir_set_dx_csum(ino_ref, (void *)dx_blks[1].b.data); + dx_blks[0].b.dirty = true; + dx_blks[1].b.dirty = true; + + ext4_dir_set_dx_csum(ino_ref, (void *)b.data); + b.dirty = true; + return ext4_block_set(ino_ref->fs->bdev, &b); } else { - /* Create second level index */ - + size_t sz; /* Copy data from root to child block */ - memcpy((void *)new_entries, (void *)entries, - leaf_count * - sizeof(struct ext4_dir_idx_entry)); - - struct ext4_dir_idx_countlimit *new_countlimit = - (struct ext4_dir_idx_countlimit *)new_entries; + sz = leaf_count * sizeof(struct ext4_dir_idx_entry); + memcpy(new_en, e, sz); - uint32_t entry_space = - block_size - - sizeof(struct ext4_fake_dir_entry); - if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) + struct ext4_dir_idx_climit *new_climit = (void*)new_en; + if (meta_csum) entry_space -= sizeof(struct ext4_dir_idx_tail); - uint32_t node_limit = - entry_space / sizeof(struct ext4_dir_idx_entry); - ext4_dir_dx_countlimit_set_limit(new_countlimit, - node_limit); + ext4_dir_dx_climit_set_limit(new_climit, node_limit); /* Set values in root node */ - struct ext4_dir_idx_countlimit - *new_root_countlimit = - (struct ext4_dir_idx_countlimit *)entries; + struct ext4_dir_idx_climit *new_root_climit = (void *)e; - ext4_dir_dx_countlimit_set_count(new_root_countlimit, - 1); - ext4_dir_dx_entry_set_block(entries, new_iblock); + ext4_dir_dx_climit_set_count(new_root_climit, 1); + ext4_dir_dx_entry_set_block(e, new_iblk); - ((struct ext4_dir_idx_root *)dx_blocks[0] - .block.data) - ->info.indirect_levels = 1; + struct ext4_dir_idx_root *r = (void *)dx_blks[0].b.data; + r->info.indirect_levels = 1; /* Add new entry to the path */ - dx_block = dx_blocks + 1; - dx_block->position = - dx_blocks->position - entries + new_entries; - dx_block->entries = new_entries; - dx_block->block = new_block; - - *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; + dxb = dx_blks + 1; + dxb->position = dx_blks->position - e + new_en; + dxb->entries = new_en; + dxb->b = b; + *new_dx_block = dxb; + + ext4_dir_set_dx_csum(ino_ref, (void *)dx_blks[0].b.data); + ext4_dir_set_dx_csum(ino_ref, (void *)dx_blks[1].b.data); + dx_blks[0].b.dirty = true; + dx_blks[1].b.dirty = true; } } @@ -1354,25 +1257,21 @@ int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent, struct ext4_inode_ref *child, const char *name) { int rc2 = EOK; - + int r; /* 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, - false); - if (rc != EOK) - return rc; + ext4_fsblk_t rblock_addr; + r = ext4_fs_get_inode_data_block_index(parent, 0, &rblock_addr, false); + if (r != EOK) + return r; struct ext4_fs *fs = parent->fs; - struct ext4_block root_block; + struct ext4_block root_blk; - rc = ext4_block_get(fs->bdev, &root_block, root_block_addr); - if (rc != EOK) - return rc; + r = ext4_block_get(fs->bdev, &root_blk, rblock_addr); + if (r != EOK) + return r; - if (!ext4_dir_dx_checksum_verify(parent, - (struct ext4_dir_entry_ll *)root_block.data)) { + if (!ext4_dir_dx_csum_verify(parent, (void*)root_blk.data)) { ext4_dbg(DEBUG_DIR_IDX, DBG_WARN "HTree root checksum failed." "Inode: %" PRIu32", " @@ -1384,9 +1283,9 @@ int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent, /* Initialize hinfo structure (mainly compute hash) */ uint32_t name_len = strlen(name); struct ext4_hash_info hinfo; - rc = ext4_dir_hinfo_init(&hinfo, &root_block, &fs->sb, name_len, name); - if (rc != EOK) { - ext4_block_set(fs->bdev, &root_block); + r = ext4_dir_hinfo_init(&hinfo, &root_blk, &fs->sb, name_len, name); + if (r != EOK) { + ext4_block_set(fs->bdev, &root_blk); return EXT4_ERR_BAD_DX_DIR; } @@ -1394,42 +1293,38 @@ 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_dir_idx_block dx_blocks[2]; - struct ext4_dir_idx_block *dx_block; + struct ext4_dir_idx_block dx_blks[2]; + struct ext4_dir_idx_block *dx_blk; struct ext4_dir_idx_block *dx_it; - rc = ext4_dir_dx_get_leaf(&hinfo, parent, &root_block, &dx_block, - dx_blocks); - if (rc != EOK) { - rc = EXT4_ERR_BAD_DX_DIR; + r = ext4_dir_dx_get_leaf(&hinfo, parent, &root_blk, &dx_blk, dx_blks); + if (r != EOK) { + r = EXT4_ERR_BAD_DX_DIR; goto release_index; } /* 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_idx = ext4_dir_dx_entry_get_block(dx_blk->position); ext4_fsblk_t leaf_block_addr; - rc = ext4_fs_get_inode_data_block_index(parent, leaf_block_idx, - &leaf_block_addr, - false); - if (rc != EOK) + r = ext4_fs_get_inode_data_block_index(parent, leaf_block_idx, + &leaf_block_addr, false); + if (r != 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) + r = ext4_dir_dx_split_index(parent, dx_blks, dx_blk, &dx_blk); + if (r != EOK) goto release_target_index; struct ext4_block target_block; - rc = ext4_block_get(fs->bdev, &target_block, leaf_block_addr); - if (rc != EOK) + r = ext4_block_get(fs->bdev, &target_block, leaf_block_addr); + if (r != EOK) goto release_index; - if (!ext4_dir_checksum_verify(parent, - (struct ext4_dir_entry_ll *)target_block.data)) { + if (!ext4_dir_csum_verify(parent,(void *)target_block.data)) { ext4_dbg(DEBUG_DIR_IDX, DBG_WARN "HTree leaf block checksum failed." "Inode: %" PRIu32", " @@ -1439,54 +1334,53 @@ int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent, } /* Check if insert operation passed */ - rc = ext4_dir_try_insert_entry(&fs->sb, parent, &target_block, child, + r = ext4_dir_try_insert_entry(&fs->sb, parent, &target_block, child, name, name_len); - if (rc == EOK) + if (r == EOK) goto release_target_index; /* Split entries to two blocks (includes sorting by hash value) */ struct ext4_block new_block; - rc = ext4_dir_dx_split_data(parent, &hinfo, &target_block, dx_block, + r = ext4_dir_dx_split_data(parent, &hinfo, &target_block, dx_blk, &new_block); - if (rc != EOK) { - rc2 = rc; + if (r != EOK) { + rc2 = r; goto release_target_index; } /* Where to save new entry */ - 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, parent, &new_block, - child, name, name_len); + uint32_t blk_hash = ext4_dir_dx_entry_get_hash(dx_blk->position + 1); + if (hinfo.hash >= blk_hash) + r = ext4_dir_try_insert_entry(&fs->sb, parent, &new_block, + child, name, name_len); else - rc = ext4_dir_try_insert_entry(&fs->sb, parent, &target_block, - child, name, name_len); + r = ext4_dir_try_insert_entry(&fs->sb, parent, &target_block, + child, name, name_len); /* Cleanup */ - rc = ext4_block_set(fs->bdev, &new_block); - if (rc != EOK) - return rc; + r = ext4_block_set(fs->bdev, &new_block); + if (r != EOK) + return r; /* Cleanup operations */ release_target_index: - rc2 = rc; + rc2 = r; - rc = ext4_block_set(fs->bdev, &target_block); - if (rc != EOK) - return rc; + r = ext4_block_set(fs->bdev, &target_block); + if (r != EOK) + return r; release_index: - if (rc != EOK) - rc2 = rc; + if (r != EOK) + rc2 = r; - dx_it = dx_blocks; + dx_it = dx_blks; - while (dx_it <= dx_block) { - rc = ext4_block_set(fs->bdev, &dx_it->block); - if (rc != EOK) - return rc; + while (dx_it <= dx_blk) { + r = ext4_block_set(fs->bdev, &dx_it->b); + if (r != EOK) + return r; dx_it++; } @@ -1508,8 +1402,7 @@ 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)) { + if (!ext4_dir_dx_csum_verify(dir, (void *)block.data)) { ext4_dbg(DEBUG_DIR_IDX, DBG_WARN "HTree root checksum failed." "Inode: %" PRIu32", " @@ -1522,11 +1415,9 @@ int ext4_dir_dx_reset_parent_inode(struct ext4_inode_ref *dir, 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_dx_dot_en_set_inode(&root->dots[1], parent_inode); - ext4_dir_set_dx_checksum(dir, - (struct ext4_dir_entry_ll *) - block.data); + ext4_dir_set_dx_csum(dir, (void *)block.data); block.dirty = true; return ext4_block_set(dir->fs->bdev, &block);