Skip to content

Commit

Permalink
cherry-pick 23-3 support multipartition base disks for proxy overlay …
Browse files Browse the repository at this point in the history
…disks (#830)

* [Blockstore] support DescribeBlocks method for disks with several partitions  (#662)

* [Blockstore] do not calculate logical used blocks metric for proxy overlay disks (#786)

* do not calculate logical used blocks metric for proxy overlay disks

* resolve issues

* add comment

* fix comment

* fix comment

* fix comment

* fix comment

* issue-356: cleanup after PR 786 (#798)

---------

Co-authored-by: Andrei Strelkovskii <[email protected]>
  • Loading branch information
BarkovBG and qkrorlqr authored Mar 27, 2024
1 parent 8b22ae9 commit c405262
Show file tree
Hide file tree
Showing 13 changed files with 467 additions and 8 deletions.
16 changes: 11 additions & 5 deletions cloud/blockstore/libs/storage/partition/part_actor_loadstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,13 @@ void TPartitionActor::CompleteLoadState(
Y_ABORT_UNLESS(State->GetGarbageQueue().AddNewBlobs(args.NewBlobs));
Y_ABORT_UNLESS(State->GetGarbageQueue().AddGarbageBlobs(args.GarbageBlobs));

if (State->GetBaseDiskId()) {
// Logical used blocks calculation is not implemented for proxy overlay
// disks with multi-partition base disks, so we disable it.
// Proxy overlay disks are system disks that are used for snapshot creation
// or disk relocation.
// Also, logical used blocks calculation is not needed for such disks
// because they are temporary and do not belong to a user.
if (State->GetBaseDiskId() && !partitionConfig.GetIsSystem()) {
if (args.ReadLogicalUsedBlocks) {
State->GetLogicalUsedBlocks() = std::move(args.LogicalUsedBlocks);
State->AccessStats().SetLogicalUsedBlocksCount(
Expand Down Expand Up @@ -287,12 +293,12 @@ void TPartitionActor::HandleGetUsedBlocksResponse(

Suicide(ctx);
return;
} else {
LOG_DEBUG(ctx, TBlockStoreComponents::PARTITION,
"[%lu] LoadState completed",
TabletID());
}

LOG_DEBUG(ctx, TBlockStoreComponents::PARTITION,
"[%lu] LoadState completed",
TabletID());

for (const auto& block: msg->Record.GetUsedBlocks()) {
State->GetLogicalUsedBlocks().Merge(
TCompressedBitmap::TSerializedChunk{
Expand Down
4 changes: 4 additions & 0 deletions cloud/blockstore/libs/storage/protos/part.proto
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ message TPartitionConfig

// Optional tablet id of base volume.
uint64 BaseDiskTabletId = 17;

// Indicates that partition does not belong to the user directly, but is
// used for system needs.
bool IsSystem = 18;
}

////////////////////////////////////////////////////////////////////////////////
Expand Down
58 changes: 58 additions & 0 deletions cloud/blockstore/libs/storage/service/service_ut_create.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,64 @@ Y_UNIT_TEST_SUITE(TServiceCreateVolumeTest)
}
}

Y_UNIT_TEST(ShouldCreateSystemVolumeWithMultipartitionedBaseDisk)
{
TTestEnv env;
NProto::TStorageServiceConfig config;
config.SetBytesPerPartition(2_GB);
config.SetBytesPerPartitionSSD(1_GB);
config.SetMultipartitionVolumesEnabled(true);
config.SetBytesPerStripe(16_MB);
config.SetMaxPartitionsPerVolume(2);
ui32 nodeIdx = SetupTestEnv(env, config);

auto& runtime = env.GetRuntime();

TServiceClient service(runtime, nodeIdx);

{
service.CreateVolume(
"baseDisk",
2_GB / DefaultBlockSize,
DefaultBlockSize,
"", // folderId
"", // cloudId
NCloud::NProto::STORAGE_MEDIA_SSD,
NProto::TVolumePerformanceProfile(),
TString(), // placementGroupId
0, // placementPartitionIndex
0, // partitionsCount
NProto::TEncryptionSpec()
);

auto response = service.DescribeVolume("baseDisk");
UNIT_ASSERT_VALUES_EQUAL(S_OK, response->GetStatus());
UNIT_ASSERT_VALUES_EQUAL(2, response->Record.GetVolume().GetPartitionsCount());

service.CreateVolume(
"vol0",
2_GB / DefaultBlockSize,
DefaultBlockSize,
TString(), // folderId
TString(), // cloudId
NCloud::NProto::STORAGE_MEDIA_SSD,
NProto::TVolumePerformanceProfile(),
TString(), // placementGroupId
0, // placementPartitionIndex
0, // partitionsCount
NProto::TEncryptionSpec(),
true, // isSystem
"baseDisk",
"baseDiskCheckpointId",
0 // fillGeneration
);

response = service.DescribeVolume("vol0");
UNIT_ASSERT_VALUES_EQUAL(S_OK, response->GetStatus());
UNIT_ASSERT_VALUES_EQUAL(1, response->Record.GetVolume().GetPartitionsCount());
}
}

Y_UNIT_TEST(ShouldCreateEncryptedVolume)
{
TTestEnv env;
Expand Down
116 changes: 116 additions & 0 deletions cloud/blockstore/libs/storage/volume/model/merge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,120 @@ void MergeStripedBitMask(
}
}

void MergeDescribeBlocksResponse(
NProto::TDescribeBlocksResponse& src,
NProto::TDescribeBlocksResponse& dst,
const ui32 blocksPerStripe,
const ui32 blockSize,
const ui32 partitionsCount,
const ui32 partitionId)
{
for (const auto& freshBlockRange: src.GetFreshBlockRanges()) {
SplitFreshBlockRangeFromRelativeToGlobalIndices(
freshBlockRange,
blocksPerStripe,
blockSize,
partitionsCount,
partitionId,
&dst);
}

const auto& srcBlobPieces = src.GetBlobPieces();

for (const auto& blobPiece: srcBlobPieces) {
NProto::TBlobPiece dstBlobPiece;
dstBlobPiece.MutableBlobId()->CopyFrom(blobPiece.GetBlobId());
dstBlobPiece.SetBSGroupId(blobPiece.GetBSGroupId());

for (const auto& srcRange: blobPiece.GetRanges()) {
SplitBlobPieceRangeFromRelativeToGlobalIndices(
srcRange,
blocksPerStripe,
partitionsCount,
partitionId,
&dstBlobPiece);
}
dst.MutableBlobPieces()->Add(std::move(dstBlobPiece));
}
}

void SplitFreshBlockRangeFromRelativeToGlobalIndices(
const NProto::TFreshBlockRange& srcRange,
const ui32 blocksPerStripe,
const ui32 blockSize,
const ui32 partitionsCount,
const ui32 partitionId,
NProto::TDescribeBlocksResponse* dst)
{
const ui32 startIndex = srcRange.GetStartIndex();
ui32 blocksCount = 0;

const char* srcRangePtr = srcRange.GetBlocksContent().Data();
while (blocksCount < srcRange.GetBlocksCount()) {
const auto index = RelativeToGlobalIndex(
blocksPerStripe,
startIndex + blocksCount,
partitionsCount,
partitionId);

const auto stripeRange = CalculateStripeRange(blocksPerStripe, index);

const auto rangeBlocksCount = std::min(
static_cast<ui64>(stripeRange.End) - index + 1,
static_cast<ui64>(srcRange.GetBlocksCount()) - blocksCount);

NProto::TFreshBlockRange dstRange;
dstRange.SetStartIndex(index);
dstRange.SetBlocksCount(rangeBlocksCount);

const ui64 bytesCount = rangeBlocksCount * blockSize;
dstRange.MutableBlocksContent()->resize(bytesCount);
char* dstRangePtr = dstRange.MutableBlocksContent()->begin();
std::memcpy(
dstRangePtr,
srcRangePtr,
bytesCount);

srcRangePtr += bytesCount;
blocksCount += rangeBlocksCount;

dst->MutableFreshBlockRanges()->Add(std::move(dstRange));
}
}

void SplitBlobPieceRangeFromRelativeToGlobalIndices(
const NProto::TRangeInBlob& srcRange,
const ui32 blocksPerStripe,
const ui32 partitionsCount,
const ui32 partitionId,
NProto::TBlobPiece* dstBlobPiece)
{
const ui32 blobOffset = srcRange.GetBlobOffset();
const ui32 blockIndex = srcRange.GetBlockIndex();
ui32 blocksCount = 0;

while (blocksCount < srcRange.GetBlocksCount()) {
const auto index = RelativeToGlobalIndex(
blocksPerStripe,
blockIndex + blocksCount,
partitionsCount,
partitionId);

const auto stripeRange = CalculateStripeRange(blocksPerStripe, index);

const auto rangeBlocksCount = std::min(
static_cast<ui64>(stripeRange.End) - index + 1,
static_cast<ui64>(srcRange.GetBlocksCount()) - blocksCount);

NProto::TRangeInBlob dstRange;
dstRange.SetBlobOffset(blobOffset + blocksCount);
dstRange.SetBlockIndex(index);
dstRange.SetBlocksCount(rangeBlocksCount);

blocksCount += rangeBlocksCount;

dstBlobPiece->MutableRanges()->Add(std::move(dstRange));
}
}

} // namespace NCloud::NBlockStore::NStorage
25 changes: 25 additions & 0 deletions cloud/blockstore/libs/storage/volume/model/merge.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <cloud/blockstore/libs/storage/protos_ydb/volume.pb.h>

#include <cloud/blockstore/libs/common/block_range.h>

namespace NCloud::NBlockStore::NStorage {
Expand All @@ -15,4 +17,27 @@ void MergeStripedBitMask(
const TString& srcMask,
TString& dstMask);

void MergeDescribeBlocksResponse(
NProto::TDescribeBlocksResponse& src,
NProto::TDescribeBlocksResponse& dst,
const ui32 blocksPerStripe,
const ui32 blockSize,
const ui32 partitionsCount,
const ui32 partitionId);

void SplitFreshBlockRangeFromRelativeToGlobalIndices(
const NProto::TFreshBlockRange& srcRange,
const ui32 blocksPerStripe,
const ui32 blockSize,
const ui32 partitionsCount,
const ui32 partitionId,
NProto::TDescribeBlocksResponse* dst);

void SplitBlobPieceRangeFromRelativeToGlobalIndices(
const NProto::TRangeInBlob& srcRange,
const ui32 blocksPerStripe,
const ui32 partitionsCount,
const ui32 partitionId,
NProto::TBlobPiece* dstBlobPiece);

} // namespace NCloud::NBlockStore::NStorage
65 changes: 65 additions & 0 deletions cloud/blockstore/libs/storage/volume/model/merge_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,71 @@ Y_UNIT_TEST_SUITE(TMergeTest)
}
}

Y_UNIT_TEST(ShouldSplitFreshBlockRangeFromRelativeToGlobalIndices)
{
NProto::TFreshBlockRange freshData;
freshData.SetStartIndex(5);
freshData.SetBlocksCount(8);
freshData.MutableBlocksContent()->append(TString(1024, 'X'));

NProto::TDescribeBlocksResponse dst;
SplitFreshBlockRangeFromRelativeToGlobalIndices(
freshData,
4, // blocksPerStripe
128, // blockSize
2, // partitionsCount
0, // partitionId
&dst);

UNIT_ASSERT_VALUES_EQUAL(3, dst.FreshBlockRangesSize());

const auto& range1 = dst.GetFreshBlockRanges(0);
UNIT_ASSERT_VALUES_EQUAL(9, range1.GetStartIndex());
UNIT_ASSERT_VALUES_EQUAL(3, range1.GetBlocksCount());

const auto& range2 = dst.GetFreshBlockRanges(1);
UNIT_ASSERT_VALUES_EQUAL(16, range2.GetStartIndex());
UNIT_ASSERT_VALUES_EQUAL(4, range2.GetBlocksCount());

TString actualContent;
for (size_t i = 0; i < dst.FreshBlockRangesSize(); ++i) {
const auto& freshRange = dst.GetFreshBlockRanges(i);
actualContent += freshRange.GetBlocksContent();
}

UNIT_ASSERT_VALUES_EQUAL(1024, actualContent.size());
for (size_t i = 0; i < actualContent.size(); i++) {
UNIT_ASSERT_VALUES_EQUAL('X', actualContent[i]);
}
}

Y_UNIT_TEST(ShouldSplitBlobPieceRangeFromRelativeToGlobalIndices)
{
NProto::TRangeInBlob rangeInBlob;
rangeInBlob.SetBlobOffset(10);
rangeInBlob.SetBlockIndex(13);
rangeInBlob.SetBlocksCount(1024);

NProto::TBlobPiece dst;
SplitBlobPieceRangeFromRelativeToGlobalIndices(
rangeInBlob,
4, // blocksPerStripe
2, // partitionsCount
0, // partitionId
&dst);

UNIT_ASSERT_VALUES_EQUAL(257, dst.RangesSize());

const auto& range1 = dst.GetRanges(0);
UNIT_ASSERT_VALUES_EQUAL(10, range1.GetBlobOffset());
UNIT_ASSERT_VALUES_EQUAL(25, range1.GetBlockIndex());
UNIT_ASSERT_VALUES_EQUAL(3, range1.GetBlocksCount());

const auto& range2 = dst.GetRanges(1);
UNIT_ASSERT_VALUES_EQUAL(13, range2.GetBlobOffset());
UNIT_ASSERT_VALUES_EQUAL(32, range2.GetBlockIndex());
UNIT_ASSERT_VALUES_EQUAL(4, range2.GetBlocksCount());
}
}

} // namespace NCloud::NBlockStore::NStorage
10 changes: 10 additions & 0 deletions cloud/blockstore/libs/storage/volume/model/stripe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ ui64 RelativeToGlobalIndex(
return stripe * blocksPerStripe + offsetInStripe;
}

TBlockRange64 CalculateStripeRange(
const ui32 blocksPerStripe,
const ui64 globalIndex)
{
const auto stripeInd = globalIndex / blocksPerStripe;
return TBlockRange64::WithLength(
stripeInd * blocksPerStripe,
blocksPerStripe);
}

ui32 CalculateRequestCount(
const ui32 blocksPerStripe,
const TBlockRange64& original,
Expand Down
4 changes: 4 additions & 0 deletions cloud/blockstore/libs/storage/volume/model/stripe.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ ui64 RelativeToGlobalIndex(
const ui32 partitionCount,
const ui32 partitionId);

TBlockRange64 CalculateStripeRange(
const ui32 blocksPerStripe,
const ui64 globalIndex);

ui32 CalculateRequestCount(
const ui32 blocksPerStripe,
const TBlockRange64& original,
Expand Down
19 changes: 19 additions & 0 deletions cloud/blockstore/libs/storage/volume/model/stripe_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,25 @@ Y_UNIT_TEST_SUITE(TStripeTest)
UNIT_ASSERT_VALUES_EQUAL(75, RelativeToGlobalIndex(10, 25, 3, 1));
}

Y_UNIT_TEST(ShouldCalculateStripeRange)
{
UNIT_ASSERT_VALUES_EQUAL(
DescribeRange(TBlockRange64::WithLength(0, 10)),
DescribeRange(CalculateStripeRange(10, 0)));

UNIT_ASSERT_VALUES_EQUAL(
DescribeRange(TBlockRange64::WithLength(0, 10)),
DescribeRange(CalculateStripeRange(10, 5)));

UNIT_ASSERT_VALUES_EQUAL(
DescribeRange(TBlockRange64::WithLength(10, 10)),
DescribeRange(CalculateStripeRange(10, 15)));

UNIT_ASSERT_VALUES_EQUAL(
DescribeRange(TBlockRange64::WithLength(10, 10)),
DescribeRange(CalculateStripeRange(10, 19)));
}

Y_UNIT_TEST(ShouldCalculateRequestCount)
{
UNIT_ASSERT_VALUES_EQUAL(
Expand Down
Loading

0 comments on commit c405262

Please sign in to comment.