diff --git a/cloud/blockstore/libs/storage/volume/volume_actor_allocatedisk.cpp b/cloud/blockstore/libs/storage/volume/volume_actor_allocatedisk.cpp index b94c09add9..8647082e9f 100644 --- a/cloud/blockstore/libs/storage/volume/volume_actor_allocatedisk.cpp +++ b/cloud/blockstore/libs/storage/volume/volume_actor_allocatedisk.cpp @@ -110,15 +110,17 @@ bool ValidateDevices( return ok; } -std::unique_ptr CreateNodeIdChangeDifferencer() +std::unique_ptr CreateLiteReallocationDifferencer() { + const auto* ioModeTsDescriptor = + NProto::TVolumeMeta::GetDescriptor()->FindFieldByName("IOModeTs"); // These are two fields that will change during disk agent blue-green // deploy. const auto* nodeIdDescriptor = NProto::TDeviceConfig::GetDescriptor()->FindFieldByName("NodeId"); const auto* rdmaPortDescriptor = NProto::TRdmaEndpoint::GetDescriptor()->FindFieldByName("Port"); - if (!nodeIdDescriptor || !rdmaPortDescriptor) { + if (!nodeIdDescriptor || !rdmaPortDescriptor || !ioModeTsDescriptor) { ReportFieldDescriptorNotFound( TStringBuilder() << "Lite reallocation is impossible. nodeIdDescriptor = " @@ -129,6 +131,7 @@ std::unique_ptr CreateNodeIdChangeDifferencer() } auto diff = std::make_unique(); + diff->IgnoreField(ioModeTsDescriptor); diff->IgnoreField(nodeIdDescriptor); diff->IgnoreField(rdmaPortDescriptor); diff->set_float_comparison( @@ -538,7 +541,7 @@ void TVolumeActor::ExecuteUpdateDevices( Y_DEBUG_ABORT_UNLESS(State->IsDiskRegistryMediaKind()); if (Config->GetAllowLiteDiskReallocations()) { - auto differencer = CreateNodeIdChangeDifferencer(); + auto differencer = CreateLiteReallocationDifferencer(); args.LiteReallocation = differencer && differencer->Compare(oldMeta, newMeta); } diff --git a/cloud/blockstore/libs/storage/volume/volume_ut.cpp b/cloud/blockstore/libs/storage/volume/volume_ut.cpp index 45a725ac49..f1c9f2287c 100644 --- a/cloud/blockstore/libs/storage/volume/volume_ut.cpp +++ b/cloud/blockstore/libs/storage/volume/volume_ut.cpp @@ -5050,10 +5050,12 @@ Y_UNIT_TEST_SUITE(TVolumeTest) Y_UNIT_TEST(ShouldDoLiteReallocations) { - auto runtime = PrepareTestActorRuntime(); + auto state = MakeIntrusive(); + auto runtime = PrepareTestActorRuntime( + NProto::TStorageServiceConfig(), state); - const auto expectedBlockCount = DefaultDeviceBlockSize * DefaultDeviceBlockCount - / DefaultBlockSize; + const auto expectedBlockCount = + DefaultDeviceBlockSize * DefaultDeviceBlockCount / DefaultBlockSize; const auto expectedDeviceCount = 3; TVolumeClient volume(*runtime); @@ -5077,6 +5079,9 @@ Y_UNIT_TEST_SUITE(TVolumeTest) auto metaHistory = volume.ReadMetaHistory(); UNIT_ASSERT_VALUES_EQUAL(S_OK, metaHistory->Error.GetCode()); UNIT_ASSERT_VALUES_EQUAL(1, metaHistory->MetaHistory.size()); + UNIT_ASSERT_VALUES_EQUAL( + 0, + metaHistory->MetaHistory[0].Meta.GetIOModeTs()); } { @@ -5149,6 +5154,34 @@ Y_UNIT_TEST_SUITE(TVolumeTest) auto metaHistory = volume.ReadMetaHistory(); UNIT_ASSERT_VALUES_EQUAL(S_OK, metaHistory->Error.GetCode()); UNIT_ASSERT_VALUES_EQUAL(2, metaHistory->MetaHistory.size()); + UNIT_ASSERT_VALUES_EQUAL( + 0, + metaHistory->MetaHistory[1].Meta.GetIOModeTs()); + } + + runtime->SetEventFilter([](TTestActorRuntimeBase&, + TAutoPtr&) { return false; }); + auto now = Now(); + state->Disks["vol0"].IOModeTs = now; + volume.ReallocateDisk(); + { + // Lite reallocation happened. Meta history still contains 2 items. + auto metaHistory = volume.ReadMetaHistory(); + UNIT_ASSERT_VALUES_EQUAL(S_OK, metaHistory->Error.GetCode()); + UNIT_ASSERT_VALUES_EQUAL(2, metaHistory->MetaHistory.size()); + } + + state->Disks["vol0"].MuteIOErrors = true; + volume.ReallocateDisk(); + { + // No lite reallocation, since MuteIOErrors has changed. Meta + // history contains 3 items now. + auto metaHistory = volume.ReadMetaHistory(); + UNIT_ASSERT_VALUES_EQUAL(S_OK, metaHistory->Error.GetCode()); + UNIT_ASSERT_VALUES_EQUAL(3, metaHistory->MetaHistory.size()); + UNIT_ASSERT_VALUES_EQUAL( + now.MicroSeconds(), + metaHistory->MetaHistory.back().Meta.GetIOModeTs()); } }