From f2cbe793e2ad185aac3e8399026d7bccc70487cd Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Sun, 9 Nov 2025 15:47:54 +0300 Subject: [PATCH] Fix intent_write_allowed check, add offset & len validation on start --- src/blockstore/blockstore_heap.cpp | 20 ++++++++++++++++++++ src/blockstore/blockstore_write.cpp | 20 +++++++++----------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/blockstore/blockstore_heap.cpp b/src/blockstore/blockstore_heap.cpp index cf51290e..6a3ea764 100644 --- a/src/blockstore/blockstore_heap.cpp +++ b/src/blockstore/blockstore_heap.cpp @@ -354,6 +354,26 @@ corrupted_object: block_num, block_offset, expected_crc32c, wr->crc32c); goto corrupted_object; } + // Verify offset & len + if ((wr->type() == BS_HEAP_SMALL_WRITE || wr->type() == BS_HEAP_INTENT_WRITE) && + (wr->small().offset+wr->small().len > dsk->data_block_size || + wr->small().offset % dsk->bitmap_granularity || + wr->small().len % dsk->bitmap_granularity)) + { + fprintf(stderr, "Error: %s entry %jx:%jx v%ju has invalid offset/length: %u/%u. Metadata is incompatible with current parameters, aborting\n", + wr->type() == BS_HEAP_SMALL_WRITE ? "small_write" : "intent_write", + wr->inode, wr->stripe, wr->version, wr->small().offset, wr->small().len); + goto corrupted_object; + } + if (wr->type() == BS_HEAP_BIG_INTENT && + (wr->big_intent().offset+wr->big_intent().len > dsk->data_block_size || + wr->big_intent().offset % dsk->bitmap_granularity || + wr->big_intent().len % dsk->bitmap_granularity)) + { + fprintf(stderr, "Error: big_intent entry %jx:%jx v%ju has invalid offset/length: %u/%u. Metadata is incompatible with current parameters, aborting\n", + wr->inode, wr->stripe, wr->version, wr->big_intent().offset, wr->big_intent().len); + goto corrupted_object; + } handle_write(block_num, wr); block_offset += wr->size; } diff --git a/src/blockstore/blockstore_write.cpp b/src/blockstore/blockstore_write.cpp index 5cd6a119..d156efca 100644 --- a/src/blockstore/blockstore_write.cpp +++ b/src/blockstore/blockstore_write.cpp @@ -72,11 +72,12 @@ bool blockstore_impl_t::intent_write_allowed(blockstore_op_t *op, heap_entry_t * { return false; } - bool ok = true, has_intent = false; + bool ok = true; heap->iterate_with_stable(obj, obj->lsn, [&](heap_entry_t *wr, bool stable) { // Intent writes are not allowed over buffered writes - if (wr->type() == BS_HEAP_SMALL_WRITE) + auto t = wr->type(); + if (t == BS_HEAP_SMALL_WRITE) { ok = false; return false; @@ -87,17 +88,14 @@ bool blockstore_impl_t::intent_write_allowed(blockstore_op_t *op, heap_entry_t * ok = false; return false; } - // One intent-write is allowed even with fsyncs because BIG_WRITE is always counted as fsynced - if (dsk.disable_data_fsync && wr->type() == BS_HEAP_INTENT_WRITE) + // Intent writes are not allowed over unfinished intent writes + if ((t == BS_HEAP_INTENT_WRITE || t == BS_HEAP_BIG_INTENT) && wr->lsn > heap->get_fsynced_lsn()) { - if (has_intent) - { - ok = false; - return false; - } - has_intent = true; + ok = false; + return false; } - if (wr->type() == BS_HEAP_BIG_WRITE || wr->type() == BS_HEAP_BIG_INTENT) + // Intent writes are allowed over BIG_WRITEs even with fsyncs because BIG_WRITE is always counted as fsynced + if (t == BS_HEAP_BIG_WRITE || t == BS_HEAP_BIG_INTENT) { return false; }