ext2: fix metadata_csum for inodes

the checksum assumes the full inode block.

Change-Id: I60ef5d0b769750107b7e104709edff95beee8085
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4118
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
Jérôme Duval
2021-06-27 12:41:01 +00:00
parent 4c23dfb3a3
commit 842a1538a6
3 changed files with 36 additions and 28 deletions
+34 -27
View File
@@ -32,6 +32,10 @@
#define ERROR(x...) dprintf("\33[34mext2:\33[0m " x)
#define EXT2_EA_CHECKSUM_SIZE (offsetof(ext2_inode, checksum_high) \
+ sizeof(uint16) - EXT2_INODE_NORMAL_SIZE)
Inode::Inode(Volume* volume, ino_t id)
:
fVolume(volume),
@@ -135,23 +139,23 @@ Inode::WriteBack(Transaction& transaction)
if (inodeBlockData == NULL)
return B_IO_ERROR;
if (fVolume->HasMetaGroupChecksumFeature()) {
uint32 checksum = _InodeChecksum();
fNode.checksum = checksum & 0xffff;
if (fNodeSize > EXT2_INODE_NORMAL_SIZE
&& fNodeSize >= offsetof(ext2_inode, change_time_extra)) {
fNode.checksum_high = checksum >> 16;
}
}
TRACE("Inode::WriteBack(): Inode ID: %" B_PRIdINO ", inode block: %"
B_PRIdOFF ", data: %p, index: %" B_PRIu32 ", inode size: %" B_PRIu32
", node size: %" B_PRIu32 ", this: %p, node: %p\n",
fID, blockNum, inodeBlockData, fVolume->InodeBlockIndex(fID),
fVolume->InodeSize(), fNodeSize, this, &fNode);
memcpy(inodeBlockData +
fVolume->InodeBlockIndex(fID) * fVolume->InodeSize(),
(uint8*)&fNode, fNodeSize);
ext2_inode* inode = (ext2_inode*)(inodeBlockData +
fVolume->InodeBlockIndex(fID) * fVolume->InodeSize());
memcpy(inode, (uint8*)&fNode, fNodeSize);
if (fVolume->HasMetaGroupChecksumFeature()) {
uint32 checksum = _InodeChecksum(inode);
inode->checksum = checksum & 0xffff;
if (fNodeSize > EXT2_INODE_NORMAL_SIZE
&& fNode.ExtraInodeSize() >= EXT2_EA_CHECKSUM_SIZE) {
inode->checksum_high = checksum >> 16;
}
}
TRACE("Inode::WriteBack() finished %" B_PRId32 "\n", Node().stream.direct[0]);
return B_OK;
@@ -186,11 +190,11 @@ Inode::UpdateNodeFromDisk()
memcpy(&fNode, inode, fNodeSize);
if (fVolume->HasMetaGroupChecksumFeature()) {
uint32 checksum = _InodeChecksum();
uint32 checksum = _InodeChecksum(inode);
uint32 provided = fNode.checksum;
if (fNodeSize > EXT2_INODE_NORMAL_SIZE
&& fNodeSize >= offsetof(ext2_inode, change_time_extra)) {
provided |= (fNode.checksum_high << 16);
&& fNode.ExtraInodeSize() >= EXT2_EA_CHECKSUM_SIZE) {
provided |= ((uint32)fNode.checksum_high << 16);
} else
checksum &= 0xffff;
if (provided != checksum) {
@@ -943,28 +947,31 @@ Inode::IncrementNumLinks(Transaction& transaction)
uint32
Inode::_InodeChecksum()
Inode::_InodeChecksum(ext2_inode* inode)
{
size_t offset = offsetof(ext2_inode, checksum);
size_t offset2 = offsetof(ext2_inode, reserved);
uint32 number = fID;
uint32 checksum = calculate_crc32c(fVolume->ChecksumSeed(), (uint8*)&number,
sizeof(number));
uint32 checksum = calculate_crc32c(fVolume->ChecksumSeed(),
(uint8*)&number, sizeof(number));
uint32 gen = fNode.generation;
checksum = calculate_crc32c(checksum, (uint8*)&gen, sizeof(gen));
checksum = calculate_crc32c(checksum, (uint8*)&fNode, offset);
checksum = calculate_crc32c(checksum, (uint8*)inode, offset);
uint16 dummy = 0;
checksum = calculate_crc32c(checksum, (uint8*)&dummy, sizeof(dummy));
checksum = calculate_crc32c(checksum, (uint8*)&fNode + offset2,
EXT2_INODE_NORMAL_SIZE - offset2);
offset += sizeof(dummy);
checksum = calculate_crc32c(checksum, (uint8*)inode + offset,
EXT2_INODE_NORMAL_SIZE - offset);
if (fNodeSize > EXT2_INODE_NORMAL_SIZE) {
offset = offsetof(ext2_inode, checksum_high);
offset2 = offsetof(ext2_inode, change_time_extra);
checksum = calculate_crc32c(checksum, (uint8*)&fNode + EXT2_INODE_NORMAL_SIZE,
offset - EXT2_INODE_NORMAL_SIZE);
checksum = calculate_crc32c(checksum, (uint8*)&dummy, sizeof(dummy));
checksum = calculate_crc32c(checksum, (uint8*)&fNode + offset2,
fNodeSize - offset2);
checksum = calculate_crc32c(checksum, (uint8*)inode
+ EXT2_INODE_NORMAL_SIZE, offset - EXT2_INODE_NORMAL_SIZE);
if (fNode.ExtraInodeSize() >= EXT2_EA_CHECKSUM_SIZE) {
checksum = calculate_crc32c(checksum, (uint8*)&dummy,
sizeof(dummy));
offset += sizeof(dummy);
}
checksum = calculate_crc32c(checksum, (uint8*)inode + offset,
fVolume->InodeSize() - offset);
}
return checksum;
}
+1 -1
View File
@@ -145,7 +145,7 @@ private:
uint64 _NumBlocks();
status_t _SetNumBlocks(uint64 numBlocks);
uint32 _InodeChecksum();
uint32 _InodeChecksum(ext2_inode* inode);
ext2_dir_entry_tail* _DirEntryTail(uint8* block) const;
uint32 _DirEntryChecksum(uint8* block, uint32 id,
@@ -483,6 +483,7 @@ struct ext2_inode {
uint32 creation_time;
uint32 creation_time_extra;
uint32 version_high;
uint32 project_id;
uint16 Mode() const { return B_LENDIAN_TO_HOST_INT16(mode); }
uint32 Flags() const { return B_LENDIAN_TO_HOST_INT32(flags); }