ext4_sb_get_desc_size(&bg_ref->fs->sb);
bool flex_bg =
- ext4_sb_has_feature_incompatible(&bg_ref->fs->sb,
- EXT4_FINCOM_FLEX_BG);
+ ext4_sb_feature_incom(&bg_ref->fs->sb, EXT4_FINCOM_FLEX_BG);
uint32_t inode_table_bcnt = inodes_per_group * inode_size / block_size;
memset(block_bitmap.data, 0, block_size);
bit_max = ext4_sb_is_super_in_bg(&bg_ref->fs->sb, bg_ref->index);
- if (!ext4_sb_has_feature_incompatible(&bg_ref->fs->sb,
- EXT4_FINCOM_META_BG) ||
+ if (!ext4_sb_feature_incom(&bg_ref->fs->sb, EXT4_FINCOM_META_BG) ||
bg_ref->index < ext4_sb_first_meta_bg(&bg_ref->fs->sb) *
dsc_per_block) {
if (bit_max) {
dsc_id = bgid / dsc_per_block;
first_meta_bg = ext4_sb_first_meta_bg(s);
- if (!ext4_sb_has_feature_incompatible(s,
- EXT4_FINCOM_META_BG) ||
+ if (!ext4_sb_feature_incom(s, EXT4_FINCOM_META_BG) ||
dsc_id < first_meta_bg)
return ext4_get32(s, first_data_block) + dsc_id + 1;
return (has_super + ext4_fs_first_bg_block_no(s, bgid));
}
+/**@brief Compute checksum of block group descriptor.
+ * @param sb Superblock
+ * @param bgid Index of block group in the filesystem
+ * @param bg Block group to compute checksum for
+ * @return Checksum value
+ */
+static uint16_t ext4_fs_bg_checksum(struct ext4_sblock *sb, uint32_t bgid,
+ struct ext4_bgroup *bg)
+{
+ /* If checksum not supported, 0 will be returned */
+ uint16_t crc = 0;
+#if CONFIG_META_CSUM_ENABLE
+ /* Compute the checksum only if the filesystem supports it */
+ if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) {
+ /* Use metadata_csum algorithm instead */
+ uint32_t le32_bgid = to_le32(bgid);
+ uint32_t orig_checksum, checksum;
+
+ /* Preparation: temporarily set bg checksum to 0 */
+ orig_checksum = bg->checksum;
+ bg->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 bgid */
+ checksum = ext4_crc32c(checksum, &le32_bgid,
+ sizeof(bgid));
+ /* Finally calculate crc32 checksum against block_group_desc */
+ checksum = ext4_crc32c(checksum, bg,
+ ext4_sb_get_desc_size(sb));
+ bg->checksum = orig_checksum;
+
+ crc = checksum & 0xFFFF;
+ return crc;
+ }
+#endif
+ if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_GDT_CSUM)) {
+ uint8_t *base = (uint8_t *)bg;
+ uint8_t *checksum = (uint8_t *)&bg->checksum;
+
+ uint32_t offset = (uint32_t)(checksum - base);
+
+ /* Convert block group index to little endian */
+ uint32_t le_group = to_le32(bgid);
+
+ /* Initialization */
+ crc = ext4_bg_crc16(~0, sb->uuid, sizeof(sb->uuid));
+
+ /* Include index of block group */
+ crc =
+ ext4_bg_crc16(crc, (uint8_t *)&le_group, sizeof(le_group));
+
+ /* Compute crc from the first part (stop before checksum field)
+ */
+ crc = ext4_bg_crc16(crc, (uint8_t *)bg, offset);
+
+ /* Skip checksum */
+ offset += sizeof(bg->checksum);
+
+ /* Checksum of the rest of block group descriptor */
+ if ((ext4_sb_feature_incom(sb, EXT4_FINCOM_64BIT)) &&
+ (offset < ext4_sb_get_desc_size(sb)))
+
+ crc = ext4_bg_crc16(crc, ((uint8_t *)bg) + offset,
+ ext4_sb_get_desc_size(sb) - offset);
+ }
+ return crc;
+}
+
+#if CONFIG_META_CSUM_ENABLE
+static bool ext4_fs_verify_bg_csum(struct ext4_sblock *sb,
+ uint32_t bgid,
+ struct ext4_bgroup *bg)
+{
+ if (!ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM))
+ return true;
+
+ return ext4_fs_bg_checksum(sb,
+ bgid,
+ bg) ==
+ to_le16(bg->checksum);
+}
+#else
+#define ext4_fs_verify_bg_csum(...) true
+#endif
+
int ext4_fs_get_block_group_ref(struct ext4_fs *fs, uint32_t bgid,
struct ext4_block_group_ref *ref)
{
ref->index = bgid;
ref->dirty = false;
+ if (!ext4_fs_verify_bg_csum(&fs->sb,
+ bgid,
+ ref->block_group)) {
+ ext4_dbg(DEBUG_FS,
+ DBG_WARN "Block group descriptor checksum failed."
+ "Block group index: %" PRIu32"\n",
+ bgid);
+ }
+
if (ext4_bg_has_flag(ref->block_group, EXT4_BLOCK_GROUP_BLOCK_UNINIT)) {
rc = ext4_fs_init_block_bitmap(ref);
if (rc != EOK) {
return EOK;
}
-/*
- * BIG FAT NOTES:
- * Currently we do not verify the checksum of block_group_desc
- * and inode.
- */
-
-/**@brief Compute checksum of block group descriptor.
- * @param sb Superblock
- * @param bgid Index of block group in the filesystem
- * @param bg Block group to compute checksum for
- * @return Checksum value
- */
-static uint16_t ext4_fs_bg_checksum(struct ext4_sblock *sb, uint32_t bgid,
- struct ext4_bgroup *bg)
-{
- /* If checksum not supported, 0 will be returned */
- uint16_t crc = 0;
-
- /* Compute the checksum only if the filesystem supports it */
- if (ext4_sb_has_feature_read_only(sb,
- EXT4_FRO_COM_METADATA_CSUM)) {
- /* Use metadata_csum algorithm instead */
- uint32_t le32_bgid = to_le32(bgid);
- uint32_t orig_checksum, checksum;
-
- /* Preparation: temporarily set bg checksum to 0 */
- orig_checksum = bg->checksum;
- bg->checksum = 0;
-
- /* First calculate crc32 checksum against fs uuid */
- checksum = ext4_crc32c(~0, sb->uuid, sizeof(sb->uuid));
- /* Then calculate crc32 checksum against bgid */
- checksum = ext4_crc32c(checksum, &le32_bgid,
- sizeof(bgid));
- /* Finally calculate crc32 checksum against block_group_desc */
- checksum = ext4_crc32c(checksum, bg,
- ext4_sb_get_desc_size(sb));
- bg->checksum = orig_checksum;
-
- crc = checksum & 0xFFFF;
- } else if (ext4_sb_has_feature_read_only(sb,
- EXT4_FRO_COM_GDT_CSUM)) {
- uint8_t *base = (uint8_t *)bg;
- uint8_t *checksum = (uint8_t *)&bg->checksum;
-
- uint32_t offset = (uint32_t)(checksum - base);
-
- /* Convert block group index to little endian */
- uint32_t le_group = to_le32(bgid);
-
- /* Initialization */
- crc = ext4_bg_crc16(~0, sb->uuid, sizeof(sb->uuid));
-
- /* Include index of block group */
- crc =
- ext4_bg_crc16(crc, (uint8_t *)&le_group, sizeof(le_group));
-
- /* Compute crc from the first part (stop before checksum field)
- */
- crc = ext4_bg_crc16(crc, (uint8_t *)bg, offset);
-
- /* Skip checksum */
- offset += sizeof(bg->checksum);
-
- /* Checksum of the rest of block group descriptor */
- if ((ext4_sb_has_feature_incompatible(
- sb, EXT4_FINCOM_64BIT)) &&
- (offset < ext4_sb_get_desc_size(sb)))
-
- crc = ext4_bg_crc16(crc, ((uint8_t *)bg) + offset,
- ext4_sb_get_desc_size(sb) - offset);
- }
- return crc;
-}
-
int ext4_fs_put_block_group_ref(struct ext4_block_group_ref *ref)
{
/* Check if reference modified */
return ext4_block_set(ref->fs->bdev, &ref->block);
}
+#if CONFIG_META_CSUM_ENABLE
static uint32_t ext4_fs_inode_checksum(struct ext4_inode_ref *inode_ref)
{
uint32_t checksum = 0;
struct ext4_sblock *sb = &inode_ref->fs->sb;
uint16_t inode_size = ext4_get16(sb, inode_size);
- if (ext4_sb_has_feature_read_only(sb,
- EXT4_FRO_COM_METADATA_CSUM)) {
+ if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) {
uint32_t orig_checksum;
uint32_t ino_index = to_le32(inode_ref->index);
ext4_inode_set_checksum(sb, inode_ref->inode, 0);
/* First calculate crc32 checksum against fs uuid */
- checksum = ext4_crc32c(~0, sb->uuid, sizeof(sb->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,
}
return checksum;
}
+#else
+#define ext4_fs_inode_checksum(...) 0
+#endif
static void ext4_fs_set_inode_checksum(struct ext4_inode_ref *inode_ref)
{
struct ext4_sblock *sb = &inode_ref->fs->sb;
- if (!ext4_sb_has_feature_read_only(sb,
- EXT4_FRO_COM_METADATA_CSUM))
+ if (!ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM))
return;
ext4_inode_set_checksum(sb, inode_ref->inode,
ext4_fs_inode_checksum(inode_ref));
}
+#if CONFIG_META_CSUM_ENABLE
+static bool ext4_fs_verify_inode_csum(struct ext4_inode_ref *inode_ref)
+{
+ struct ext4_sblock *sb = &inode_ref->fs->sb;
+ if (!ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM))
+ return true;
+
+ return ext4_inode_get_checksum(sb, inode_ref->inode) ==
+ ext4_fs_inode_checksum(inode_ref);
+}
+#else
+#define ext4_fs_verify_inode_csum(...) true
+#endif
+
int ext4_fs_get_inode_ref(struct ext4_fs *fs, uint32_t index,
struct ext4_inode_ref *ref)
{
ref->fs = fs;
ref->dirty = false;
+ if (!ext4_fs_verify_inode_csum(ref)) {
+ ext4_dbg(DEBUG_FS,
+ DBG_WARN "Inode checksum failed."
+ "Inode: %" PRIu32"\n",
+ ref->index);
+ }
+
return EOK;
}
(void)fs;
#if CONFIG_EXTENT_ENABLE
/* Initialize extents if needed */
- if (ext4_sb_has_feature_incompatible(&fs->sb,
- EXT4_FINCOM_EXTENTS)) {
+ if (ext4_sb_feature_incom(&fs->sb, EXT4_FINCOM_EXTENTS)) {
ext4_inode_set_flag(inode, EXT4_INODE_FLAG_EXTENTS);
/* Initialize extent root header */
if (inode_size > EXT4_GOOD_OLD_INODE_SIZE)
ext4_inode_set_extra_isize(inode,
sizeof(struct ext4_inode) -
- ext4_offsetof(struct ext4_inode,
+ offsetof(struct ext4_inode,
extra_isize));
/* Reset blocks array. For symbolic link inode, just
int rc;
#if CONFIG_EXTENT_ENABLE
/* For extents must be data block destroyed by other way */
- if ((ext4_sb_has_feature_incompatible(&fs->sb,
- EXT4_FINCOM_EXTENTS)) &&
+ if ((ext4_sb_feature_incom(&fs->sb, EXT4_FINCOM_EXTENTS)) &&
(ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
/* Data structures are released during truncate operation... */
goto finish;
/* Extents are handled otherwise = there is not support in this function
*/
ext4_assert(!(
- ext4_sb_has_feature_incompatible(&fs->sb,
- EXT4_FINCOM_EXTENTS) &&
+ ext4_sb_feature_incom(&fs->sb, EXT4_FINCOM_EXTENTS) &&
(ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))));
struct ext4_inode *inode = inode_ref->inode;
block_size;
uint32_t diff_blocks_count = old_blocks_count - new_blocks_count;
#if CONFIG_EXTENT_ENABLE
- if ((ext4_sb_has_feature_incompatible(sb,
- EXT4_FINCOM_EXTENTS)) &&
+ if ((ext4_sb_feature_incom(sb, EXT4_FINCOM_EXTENTS)) &&
(ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
/* Extents require special operation */
static int ext4_fs_get_inode_data_block_idx(struct ext4_inode_ref *inode_ref,
uint64_t iblock, ext4_fsblk_t *fblock,
bool extent_create,
- bool support_unwritten)
+ bool support_unwritten __unused)
{
struct ext4_fs *fs = inode_ref->fs;
(void)extent_create;
#if CONFIG_EXTENT_ENABLE
/* Handle i-node using extents */
- if ((ext4_sb_has_feature_incompatible(&fs->sb,
- EXT4_FINCOM_EXTENTS)) &&
+ if ((ext4_sb_feature_incom(&fs->sb, EXT4_FINCOM_EXTENTS)) &&
(ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
ext4_fsblk_t current_fsblk;
#if CONFIG_EXTENT_ENABLE
/* Handle inode using extents */
- if ((ext4_sb_has_feature_incompatible(&fs->sb,
- EXT4_FINCOM_EXTENTS)) &&
+ if ((ext4_sb_feature_incom(&fs->sb, EXT4_FINCOM_EXTENTS)) &&
(ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
/* Not reachable */
return ENOTSUP;
{
#if CONFIG_EXTENT_ENABLE
/* Handle extents separately */
- if ((ext4_sb_has_feature_incompatible(&inode_ref->fs->sb,
- EXT4_FINCOM_EXTENTS)) &&
+ if ((ext4_sb_feature_incom(&inode_ref->fs->sb, EXT4_FINCOM_EXTENTS)) &&
(ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
int rc;
ext4_fsblk_t current_fsblk;
ext4_inode_set_links_count(inode_ref->inode, link);
bool is_dx =
- ext4_sb_has_feature_compatible(&inode_ref->fs->sb,
- EXT4_FCOM_DIR_INDEX) &&
+ ext4_sb_feature_com(&inode_ref->fs->sb, EXT4_FCOM_DIR_INDEX) &&
ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_INDEX);
if (is_dx && link > 1) {