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 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) Inode::Inode(Volume* volume, ino_t id)
: :
fVolume(volume), fVolume(volume),
@@ -135,23 +139,23 @@ Inode::WriteBack(Transaction& transaction)
if (inodeBlockData == NULL) if (inodeBlockData == NULL)
return B_IO_ERROR; 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: %" TRACE("Inode::WriteBack(): Inode ID: %" B_PRIdINO ", inode block: %"
B_PRIdOFF ", data: %p, index: %" B_PRIu32 ", inode size: %" B_PRIu32 B_PRIdOFF ", data: %p, index: %" B_PRIu32 ", inode size: %" B_PRIu32
", node size: %" B_PRIu32 ", this: %p, node: %p\n", ", node size: %" B_PRIu32 ", this: %p, node: %p\n",
fID, blockNum, inodeBlockData, fVolume->InodeBlockIndex(fID), fID, blockNum, inodeBlockData, fVolume->InodeBlockIndex(fID),
fVolume->InodeSize(), fNodeSize, this, &fNode); fVolume->InodeSize(), fNodeSize, this, &fNode);
memcpy(inodeBlockData + ext2_inode* inode = (ext2_inode*)(inodeBlockData +
fVolume->InodeBlockIndex(fID) * fVolume->InodeSize(), fVolume->InodeBlockIndex(fID) * fVolume->InodeSize());
(uint8*)&fNode, fNodeSize); 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]); TRACE("Inode::WriteBack() finished %" B_PRId32 "\n", Node().stream.direct[0]);
return B_OK; return B_OK;
@@ -186,11 +190,11 @@ Inode::UpdateNodeFromDisk()
memcpy(&fNode, inode, fNodeSize); memcpy(&fNode, inode, fNodeSize);
if (fVolume->HasMetaGroupChecksumFeature()) { if (fVolume->HasMetaGroupChecksumFeature()) {
uint32 checksum = _InodeChecksum(); uint32 checksum = _InodeChecksum(inode);
uint32 provided = fNode.checksum; uint32 provided = fNode.checksum;
if (fNodeSize > EXT2_INODE_NORMAL_SIZE if (fNodeSize > EXT2_INODE_NORMAL_SIZE
&& fNodeSize >= offsetof(ext2_inode, change_time_extra)) { && fNode.ExtraInodeSize() >= EXT2_EA_CHECKSUM_SIZE) {
provided |= (fNode.checksum_high << 16); provided |= ((uint32)fNode.checksum_high << 16);
} else } else
checksum &= 0xffff; checksum &= 0xffff;
if (provided != checksum) { if (provided != checksum) {
@@ -943,28 +947,31 @@ Inode::IncrementNumLinks(Transaction& transaction)
uint32 uint32
Inode::_InodeChecksum() Inode::_InodeChecksum(ext2_inode* inode)
{ {
size_t offset = offsetof(ext2_inode, checksum); size_t offset = offsetof(ext2_inode, checksum);
size_t offset2 = offsetof(ext2_inode, reserved);
uint32 number = fID; uint32 number = fID;
uint32 checksum = calculate_crc32c(fVolume->ChecksumSeed(), (uint8*)&number, uint32 checksum = calculate_crc32c(fVolume->ChecksumSeed(),
sizeof(number)); (uint8*)&number, sizeof(number));
uint32 gen = fNode.generation; uint32 gen = fNode.generation;
checksum = calculate_crc32c(checksum, (uint8*)&gen, sizeof(gen)); 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; uint16 dummy = 0;
checksum = calculate_crc32c(checksum, (uint8*)&dummy, sizeof(dummy)); checksum = calculate_crc32c(checksum, (uint8*)&dummy, sizeof(dummy));
checksum = calculate_crc32c(checksum, (uint8*)&fNode + offset2, offset += sizeof(dummy);
EXT2_INODE_NORMAL_SIZE - offset2); checksum = calculate_crc32c(checksum, (uint8*)inode + offset,
EXT2_INODE_NORMAL_SIZE - offset);
if (fNodeSize > EXT2_INODE_NORMAL_SIZE) { if (fNodeSize > EXT2_INODE_NORMAL_SIZE) {
offset = offsetof(ext2_inode, checksum_high); offset = offsetof(ext2_inode, checksum_high);
offset2 = offsetof(ext2_inode, change_time_extra); checksum = calculate_crc32c(checksum, (uint8*)inode
checksum = calculate_crc32c(checksum, (uint8*)&fNode + EXT2_INODE_NORMAL_SIZE, + EXT2_INODE_NORMAL_SIZE, offset - EXT2_INODE_NORMAL_SIZE);
offset - EXT2_INODE_NORMAL_SIZE); if (fNode.ExtraInodeSize() >= EXT2_EA_CHECKSUM_SIZE) {
checksum = calculate_crc32c(checksum, (uint8*)&dummy, sizeof(dummy)); checksum = calculate_crc32c(checksum, (uint8*)&dummy,
checksum = calculate_crc32c(checksum, (uint8*)&fNode + offset2, sizeof(dummy));
fNodeSize - offset2); offset += sizeof(dummy);
}
checksum = calculate_crc32c(checksum, (uint8*)inode + offset,
fVolume->InodeSize() - offset);
} }
return checksum; return checksum;
} }
+1 -1
View File
@@ -145,7 +145,7 @@ private:
uint64 _NumBlocks(); uint64 _NumBlocks();
status_t _SetNumBlocks(uint64 numBlocks); status_t _SetNumBlocks(uint64 numBlocks);
uint32 _InodeChecksum(); uint32 _InodeChecksum(ext2_inode* inode);
ext2_dir_entry_tail* _DirEntryTail(uint8* block) const; ext2_dir_entry_tail* _DirEntryTail(uint8* block) const;
uint32 _DirEntryChecksum(uint8* block, uint32 id, uint32 _DirEntryChecksum(uint8* block, uint32 id,
@@ -483,6 +483,7 @@ struct ext2_inode {
uint32 creation_time; uint32 creation_time;
uint32 creation_time_extra; uint32 creation_time_extra;
uint32 version_high; uint32 version_high;
uint32 project_id;
uint16 Mode() const { return B_LENDIAN_TO_HOST_INT16(mode); } uint16 Mode() const { return B_LENDIAN_TO_HOST_INT16(mode); }
uint32 Flags() const { return B_LENDIAN_TO_HOST_INT32(flags); } uint32 Flags() const { return B_LENDIAN_TO_HOST_INT32(flags); }