ref: 7359de438cfaac829c4ed8b39fae9bb872fb5eea
parent: ed767b2a182e8297f97602b68d49e018b5e4b129
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Fri Feb 16 21:21:42 EST 2024
ext4srv: fix meta csum producing garbage A block was never cleared before setting the field. This would result in garbage and wrong checksums. Also enable checksum verification now that it actually works.
--- a/sys/src/cmd/ext4srv/ext4_dir.c
+++ b/sys/src/cmd/ext4srv/ext4_dir.c
@@ -58,14 +58,16 @@
t = ext4_dir_get_tail(inode_ref, dirent);
if (!t) {
/* There is no space to hold the checksum */
+ werrstr("no space for checksum");
return false;
}
intptr diff = (char *)t - (char *)dirent;
u32int csum = ext4_dir_csum(inode_ref, dirent, diff);
- if (t->checksum != to_le32(csum))
+ if (t->checksum != to_le32(csum)) {
+ werrstr("checksum does not match");
return false;
-
+ }
}
return true;
}
@@ -92,8 +94,7 @@
}
intptr diff = (char *)t - (char *)dirent;
- u32int csum = ext4_dir_csum(inode_ref, dirent, diff);
- t->checksum = to_le32(csum);
+ t->checksum = to_le32(ext4_dir_csum(inode_ref, dirent, diff));
}
}
@@ -305,9 +306,8 @@
/* Needed to clear dir index flag if corrupted */
ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);
parent->dirty = true;
- } else if (r == 0) {
- return 0;
}
+ return r;
}
/* Linear algorithm */
@@ -377,8 +377,7 @@
ext4_dir_write_entry(sb, blk_en, el, child, name, name_len);
ext4_dir_init_entry_tail(EXT4_DIRENT_TAIL(b.data, block_size));
} else {
- ext4_dir_write_entry(sb, blk_en, block_size, child, name,
- name_len);
+ ext4_dir_write_entry(sb, blk_en, block_size, child, name, name_len);
}
ext4_dir_set_csum(parent, (void *)b.data);
@@ -408,9 +407,8 @@
/* Needed to clear dir index flag if corrupted */
ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);
parent->dirty = true;
- } else if (r == 0) {
- return 0;
}
+ return r;
}
/* Linear algorithm */
--- a/sys/src/cmd/ext4srv/ext4_dir_idx.c
+++ b/sys/src/cmd/ext4srv/ext4_dir_idx.c
@@ -232,10 +232,6 @@
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_csum_verify(struct ext4_inode_ref *inode_ref,
struct ext4_dir_en *de)
{
@@ -262,7 +258,7 @@
u32int c = to_le32(ext4_dir_dx_checksum(inode_ref, de, coff, cnt, t));
if (t->checksum != c)
- return true; // FIXME lwext4 does not set correct checksums sometimes
+ return false;
}
return true;
}
@@ -292,8 +288,7 @@
}
t = (void *)(((struct ext4_dir_idx_entry *)climit) + limit);
- t->checksum = to_le32(ext4_dir_dx_checksum(inode_ref, dirent,
- coff, count, t));
+ t->checksum = to_le32(ext4_dir_dx_checksum(inode_ref, dirent, coff, count, t));
}
}
@@ -388,6 +383,7 @@
if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) {
int len = block_size - sizeof(struct ext4_dir_entry_tail);
+ memset(be, 0, len);
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);
@@ -1211,6 +1207,8 @@
"Block: %ud\n",
parent->index,
(u32int)0);
+ werrstr("htree root checksum mismatch");
+ return EXT4_ERR_BAD_DX_DIR;
}
/* Initialize hinfo structure (mainly compute hash) */
@@ -1263,6 +1261,9 @@
"Block: %ud\n",
parent->index,
leaf_block_idx);
+ r = -1;
+ werrstr("htree leaf block checksum mismatch");
+ goto release_index;
}
/* Check if insert operation passed */