Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions cloud/blockstore/libs/storage/partition/part_cleanup_logic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,26 +96,34 @@ TVerifyBlocksMetaResult VerifyMixedBlocksMeta(

struct TVisitor final: public IMixedBlocksIndexVisitor
{
TPartialBlobId OriginalBlobId;
TVector<TBlock> LeakedBlocks;

TVisitor(TPartialBlobId originalBlobId)
: OriginalBlobId(originalBlobId)
{}

bool VisitBlock(
ui32 blockIndex,
ui64 commitId,
const TPartialBlobId& blobId,
ui16 blobOffset,
ui8 compactionRangeCount) override
{
Y_UNUSED(blobId);
Y_UNUSED(blobOffset);
Y_UNUSED(compactionRangeCount);

if (blobId != OriginalBlobId) {
return true;
}
Comment on lines +116 to +118

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep mismatched mixed-block keys out of original-meta cleanup

When this verifier is reached from cleanup, UseRecreatedBlobMeta is false because the recreated-meta path returns before verification, so PrepareCleanupTransaction still queues the original DB blob meta for deletion. In the duplicate-flush case this branch now treats a missing original block as safe when the same (blockIndex, commitId) key belongs to another blob, but ExecuteCleanupTransaction later deletes mixed blocks by (blockIndex, commitId) only via state.DeleteMixedBlock, so cleanup of the old blob will remove the other blob's live index entry. Please keep this as a mismatch or otherwise avoid deleting the original-meta block when the index row is owned by another blob.

Useful? React with 👍 / 👎.


LeakedBlocks.emplace_back(blockIndex, commitId, false);

return true;
}
};

TVisitor visitor;
TVisitor visitor{originalBlobId};
bool ready = db.FindMixedBlocks(visitor, missedBlocks);
if (!ready) {
return {.Ready = false};
Expand Down Expand Up @@ -302,7 +310,8 @@ void ExecuteCleanupTransaction(
}
} else {
// each block has its own commitId
Y_ABORT_UNLESS(mixedBlocks.BlocksSize() == mixedBlocks.CommitIdsSize());
Y_ABORT_UNLESS(
mixedBlocks.BlocksSize() == mixedBlocks.CommitIdsSize());
for (size_t j = 0; j < mixedBlocks.BlocksSize(); ++j) {
ui32 blockIndex = mixedBlocks.GetBlocks(j);
ui64 commitId = mixedBlocks.GetCommitIds(j);
Expand Down Expand Up @@ -342,16 +351,16 @@ void ExecuteCleanupTransaction(

++mergedBlobsCount;
if (!IsDeletionMarker(item.BlobId)) {
// Mins for block counts are needed due to some inconsistencies caused by
// NBS-1422
// Mins for block counts are needed due to some inconsistencies
// caused by NBS-1422
ui64 delta = blockRange.Size() - mergedBlocks.GetSkipped();
state.DecrementMergedBlocksCount(
Min(delta, state.GetMergedBlocksCount()));
}
}

LOG_DEBUG(
*actorSystem,
*actorSystem,
TBlockStoreComponents::PARTITION,
"%s Delete blob: %s",
logTitle.GetWithTime().c_str(),
Expand Down
32 changes: 32 additions & 0 deletions cloud/blockstore/libs/storage/partition/part_cleanup_logic_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,38 @@ Y_UNIT_TEST_SUITE(TVerifyRecreatedBlobMetaTest)
});
}

Y_UNIT_TEST(ShouldRejectLeakedBlocksInRecreatedMixedMetaOnlyIfBlobIdMatches)
{
TTestExecutor executor;
executor.WriteTx([](TPartitionDatabase db) { db.InitSchema(); });

TPartialBlobId blobId;
executor.WriteTx(
[&](TPartitionDatabase db)
{
blobId = executor.MakeBlobId(1);

auto anotherBlobId = executor.MakeBlobId(1);
db.WriteMixedBlock({anotherBlobId, 1, 0, 0, 0});
});

const auto blobMeta = MakeMixedBlobMeta({0}, {1});
const auto recreatedBlobMeta = MakeMixedBlobMeta({}, {});

executor.ReadTx(
[&](TPartitionDatabase db)
{
const auto result = VerifyRecreatedBlobMeta(
db,
blobId,
blobMeta,
recreatedBlobMeta);

UNIT_ASSERT(result.Ready);
UNIT_ASSERT(!HasError(result.Error));
});
}

Y_UNIT_TEST(ShouldRejectExtraBlocksInRecreatedMixedMeta)
{
TTestExecutor executor;
Expand Down
Loading