Fix incorrect checksums for small initial writes in the old store

Details:
- Write size should be exactly csum_block_size (4k by default)
- Write should be made into a new object (unallocated space)
- In this case, the checksum of the block was calculated as if the block was
  padded with extra (2^32 - size) zero bytes due to a simple integer overflow
- As a cherry on the cake, such calculation was 'slightly' slow because it
  was processing almost 4 GB of zeroes for a small write
This commit is contained in:
Vitaliy Filippov
2026-01-16 01:07:39 +03:00
parent 819f5b7ec9
commit ddd755a0e6
2 changed files with 3 additions and 1 deletions
+1 -1
View File
@@ -183,7 +183,7 @@ bool blockstore_impl_t::enqueue_write(blockstore_op_t *op)
uint32_t end = (op->offset+op->len-1) / dsk.csum_block_size;
auto fn = state & BS_ST_BIG_WRITE ? crc32c_pad : crc32c_nopad;
if (start == end)
data_csums[0] = fn(0, op->buf, op->len, op->offset - start*dsk.csum_block_size, end*dsk.csum_block_size - (op->offset+op->len));
data_csums[0] = fn(0, op->buf, op->len, op->offset - start*dsk.csum_block_size, (end+1)*dsk.csum_block_size - (op->offset+op->len));
else
{
// First block
+2
View File
@@ -37,6 +37,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <assert.h>
#include "crc32c.h"
#ifdef WITH_ISAL
@@ -394,6 +395,7 @@ static uint8_t zero_page[4096] = {};
uint32_t crc32c_pad(uint32_t prev_crc, const void *buf, size_t len, size_t left_pad, size_t right_pad)
{
assert(left_pad < 0x10000000 && right_pad < 0x10000000);
uint32_t r = prev_crc;
while (left_pad >= 4096)
{