From 0ab2620b870c0174eeea2791a783d0b7fbedf652 Mon Sep 17 00:00:00 2001 From: Kirill Pleshivtsev Date: Thu, 30 Jan 2025 13:53:16 +0700 Subject: [PATCH] Fix the error of dropping the HwProblems flag when receiving E_IO_SILENT (#2939) * Fix the error of dropping the HwProblems flag when receiving E_IO_SILENT * Test --- cloud/blockstore/libs/client/session_ut.cpp | 61 +++++++++++++++++++++ cloud/storage/core/libs/common/error.h | 36 +++++++----- 2 files changed, 83 insertions(+), 14 deletions(-) diff --git a/cloud/blockstore/libs/client/session_ut.cpp b/cloud/blockstore/libs/client/session_ut.cpp index 8c15e5867dd..babb7f0719a 100644 --- a/cloud/blockstore/libs/client/session_ut.cpp +++ b/cloud/blockstore/libs/client/session_ut.cpp @@ -1757,6 +1757,67 @@ Y_UNIT_TEST_SUITE(TSessionTest) // Unfreeze request handlers promise.SetValue(); } + + Y_UNIT_TEST(ShouldPassErrorFlags) + { + auto client = std::make_shared(); + + size_t sessionNum = 0; + client->MountVolumeHandler = + [&](std::shared_ptr request) + { + NProto::TMountVolumeResponse response; + response.SetSessionId(ToString(++sessionNum)); + + auto& volume = *response.MutableVolume(); + volume.SetDiskId(request->GetDiskId()); + volume.SetBlockSize(4 * 1024); + volume.SetBlocksCount(1024); + + return MakeFuture(response); + }; + + client->UnmountVolumeHandler = + [](std::shared_ptr request) + { + Y_UNUSED(request); + return MakeFuture(); + }; + + client->WriteBlocksLocalHandler = + [](std::shared_ptr request) + { + Y_UNUSED(request); + + NProto::TError result = MakeError( + E_IO_SILENT, + "IO error", + NCloud::NProto::EF_HW_PROBLEMS_DETECTED); + return MakeFuture( + TErrorResponse(std::move(result))); + }; + + auto bootstrap = CreateBootstrap(client); + + auto session = bootstrap->GetSession(); + + bootstrap->Start(); + + { + auto res = session->MountVolume().GetValueSync(); + UNIT_ASSERT_C(!HasError(res), res.GetError().GetMessage()); + } + + { + auto res = WriteBlocks(session); + UNIT_ASSERT(res.GetError().GetCode() == E_IO_SILENT); + UNIT_ASSERT( + res.GetError().GetFlags() == + NCloud::NProto::EF_HW_PROBLEMS_DETECTED); + } + + bootstrap->Stop(); + } } } // namespace NCloud::NBlockStore::NClient diff --git a/cloud/storage/core/libs/common/error.h b/cloud/storage/core/libs/common/error.h index 92ca5e4f961..636a861363b 100644 --- a/cloud/storage/core/libs/common/error.h +++ b/cloud/storage/core/libs/common/error.h @@ -252,10 +252,10 @@ concept TAcceptsError = requires(T a) }; template -T ErrorResponse(ui32 code, TString message) +T ErrorResponse(ui32 code, TString message, ui32 flags = 0) { T response; - *response.MutableError() = MakeError(code, std::move(message)); + *response.MutableError() = MakeError(code, std::move(message), flags); return response; } @@ -390,40 +390,48 @@ class TResultOrError class TErrorResponse { private: - const ui32 Code; - const TString Message; + NProto::TError Error; public: - TErrorResponse(ui32 code, TString message = {}) - : Code(code) - , Message(std::move(message)) + TErrorResponse(ui32 code, TString message = {}, ui32 flags = 0) + : Error(MakeError(code, std::move(message), flags)) {} TErrorResponse(const NProto::TError& e) - : Code(e.GetCode()) - , Message(e.GetMessage()) + : Error(e) + {} + + TErrorResponse(NProto::TError&& e) + : Error(std::move(e)) {} TErrorResponse(const TServiceError& e) - : Code(e.GetCode()) - , Message(e.GetMessage()) + : Error(MakeError(e.GetCode(), TString(e.GetMessage()))) {} template operator T() const { - return ErrorResponse(Code, Message); + return ErrorResponse( + Error.GetCode(), + Error.GetMessage(), + Error.GetFlags()); } template operator TResultOrError() const { - return MakeError(Code, Message); + return TResultOrError(Error); } operator NProto::TError() const { - return MakeError(Code, Message); + return Error; + } + + operator NProto::TError&& () && + { + return std::move(Error); } };