-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[NBS] Asynchronous disks allocation #2763
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -749,7 +749,7 @@ void TDiskRegistryState::ProcessDirtyDevices(TVector<TDirtyDevice> dirtyDevices) | |
{ | ||
for (auto&& [uuid, diskId]: dirtyDevices) { | ||
if (!diskId.empty()) { | ||
auto error = PendingCleanup.Insert(diskId, std::move(uuid)); | ||
auto error = PendingCleanup.Insert(diskId, std::move(uuid), /*allocation=*/false); | ||
if (HasError(error)) { | ||
ReportDiskRegistryInsertToPendingCleanupFailed( | ||
TStringBuilder() | ||
|
@@ -1299,16 +1299,23 @@ NProto::TError TDiskRegistryState::ReplaceDeviceWithoutDiskStateUpdate( | |
} | ||
|
||
if (!manual && !deviceReplacementId.empty()) { | ||
auto cleaningDiskId = | ||
auto [allocating, deallocating] = | ||
PendingCleanup.FindDiskId(deviceReplacementId); | ||
if (!cleaningDiskId.empty() && cleaningDiskId != diskId) { | ||
if (!allocating || *allocating != diskId) { | ||
allocating = std::nullopt; | ||
} | ||
if (!deallocating || *deallocating != diskId) { | ||
deallocating = std::nullopt; | ||
} | ||
auto owningDisk = allocating ? allocating : deallocating; | ||
if (owningDisk) { | ||
return MakeError( | ||
E_ARGUMENT, | ||
TStringBuilder() | ||
<< "can't allocate specific device " | ||
<< deviceReplacementId.Quote() << " for disk " << diskId | ||
<< " since it is in pending cleanup for disk " | ||
<< cleaningDiskId); | ||
<< *owningDisk); | ||
} | ||
} | ||
|
||
|
@@ -1414,7 +1421,7 @@ NProto::TError TDiskRegistryState::ReplaceDeviceWithoutDiskStateUpdate( | |
UpdatePlacementGroup(db, diskId, disk, "ReplaceDevice"); | ||
UpdateAndReallocateDisk(db, diskId, disk); | ||
|
||
error = PendingCleanup.Insert(diskId, deviceId); | ||
error = PendingCleanup.Insert(diskId, deviceId, /*allocation=*/false); | ||
if (HasError(error)) { | ||
ReportDiskRegistryInsertToPendingCleanupFailed( | ||
TStringBuilder() << "An error occurred while replacing device: " | ||
|
@@ -2756,6 +2763,37 @@ NProto::TError TDiskRegistryState::AllocateSimpleDisk( | |
params.BlockSize << " bytes"); | ||
} | ||
|
||
// check that we can secure erase each dirty allocated device | ||
TVector<TString> dirtyDevices; | ||
for (const auto& device: allocatedDevices) { | ||
const auto& uuid = device.GetDeviceUUID(); | ||
if (!IsDirtyDevice(uuid)) { | ||
continue; | ||
} | ||
// if we can't secure erase one of allocated disk's dirty devices, we can't allocate the disk | ||
if (!CanSecureErase(uuid)) { | ||
onError(); | ||
|
||
return MakeError(E_BS_DISK_ALLOCATION_FAILED, TStringBuilder() << | ||
"can't secure erase device " << uuid); | ||
} | ||
dirtyDevices.push_back(uuid); | ||
result->DirtyDevices.push_back(device); | ||
} | ||
|
||
if (dirtyDevices) { | ||
NProto::TError cleanupError = PendingCleanup.Insert(params.DiskId, std::move(dirtyDevices), /*allocation=*/true); | ||
// if we can't secure erase one of allocated disk's dirty devices, we can't allocate the disk | ||
if (HasError(cleanupError)) { | ||
onError(); | ||
|
||
ReportDiskRegistryInsertToPendingCleanupFailed( | ||
TStringBuilder() << "An error occurred while allocating disk: " | ||
<< FormatError(cleanupError)); | ||
return cleanupError; | ||
} | ||
} | ||
|
||
for (const auto& device: allocatedDevices) { | ||
disk.Devices.push_back(device.GetDeviceUUID()); | ||
} | ||
|
@@ -2851,7 +2889,7 @@ NProto::TError TDiskRegistryState::DeallocateDisk( | |
JoinSeq(", ", devicesAllowedToBeCleaned).c_str()); | ||
|
||
auto error = | ||
PendingCleanup.Insert(diskId, std::move(devicesAllowedToBeCleaned)); | ||
PendingCleanup.Insert(diskId, std::move(devicesAllowedToBeCleaned), /*allocation=*/false); | ||
if (HasError(error)) { | ||
ReportDiskRegistryInsertToPendingCleanupFailed( | ||
TStringBuilder() << "An error occurred while deallocating disk: " | ||
|
@@ -2998,6 +3036,11 @@ auto TDiskRegistryState::DeallocateSimpleDisk( | |
db.UpdateDirtyDevice(uuid, diskId); | ||
} | ||
|
||
auto agents = FindDiskDevicesAgents(disk); | ||
for (const auto* agent: agents) { | ||
DeviceList.UpdateDevices(*agent, DevicePoolConfigs); | ||
} | ||
|
||
DeleteAllDeviceMigrations(diskId); | ||
DeleteDisk(db, diskId); | ||
|
||
|
@@ -3855,16 +3898,20 @@ bool TDiskRegistryState::MarkDeviceAsDirty( | |
return true; | ||
} | ||
|
||
TDiskRegistryState::TDiskId TDiskRegistryState::MarkDeviceAsClean( | ||
TDiskRegistryState::TOpt2Disk TDiskRegistryState::MarkDeviceAsClean( | ||
TInstant now, | ||
TDiskRegistryDatabase& db, | ||
const TDeviceId& uuid) | ||
{ | ||
auto ret = MarkDevicesAsClean(now, db, TVector<TDeviceId>{uuid}); | ||
return ret.empty() ? "" : ret[0]; | ||
auto [alloc, dealloc] = MarkDevicesAsClean(now, db, TVector<TDeviceId>{uuid}); | ||
return { | ||
alloc.empty() ? std::nullopt : std::make_optional(std::move(alloc[0])), | ||
dealloc.empty() ? std::nullopt | ||
: std::make_optional(std::move(dealloc[0]))}; | ||
} | ||
|
||
TVector<TDiskRegistryState::TDiskId> TDiskRegistryState::MarkDevicesAsClean( | ||
std::pair<TDiskRegistryState::TAllocatedDisksList, TDiskRegistryState::TDellocatedDisksList> | ||
TDiskRegistryState::MarkDevicesAsClean( | ||
TInstant now, | ||
TDiskRegistryDatabase& db, | ||
const TVector<TDeviceId>& uuids) | ||
|
@@ -3878,14 +3925,19 @@ TVector<TDiskRegistryState::TDiskId> TDiskRegistryState::MarkDevicesAsClean( | |
} | ||
} | ||
|
||
TVector<TDiskId> ret; | ||
TAllocatedDisksList allocatedDisks; | ||
TDellocatedDisksList dellocatedDisks; | ||
for (const auto& uuid: TryUpdateDevices(now, db, uuids)) { | ||
if (auto diskId = PendingCleanup.EraseDevice(uuid); !diskId.empty()) { | ||
ret.push_back(std::move(diskId)); | ||
auto [allocatedDisk, deallocatedDisk] = PendingCleanup.EraseDevice(uuid); | ||
if (allocatedDisk) { | ||
allocatedDisks.push_back(std::move(*allocatedDisk)); | ||
} | ||
if (deallocatedDisk) { | ||
dellocatedDisks.push_back(std::move(*deallocatedDisk)); | ||
} | ||
} | ||
|
||
return ret; | ||
return {std::move(allocatedDisks), std::move(dellocatedDisks)}; | ||
} | ||
|
||
bool TDiskRegistryState::TryUpdateDevice( | ||
|
@@ -4811,7 +4863,7 @@ void TDiskRegistryState::RemoveFinishedMigrations( | |
|
||
DeviceList.ReleaseDevice(m.DeviceId); | ||
db.UpdateDirtyDevice(m.DeviceId, diskId); | ||
auto error = PendingCleanup.Insert(diskId, m.DeviceId); | ||
auto error = PendingCleanup.Insert(diskId, m.DeviceId, /*allocation=*/false); | ||
if (HasError(error)) { | ||
ReportDiskRegistryInsertToPendingCleanupFailed( | ||
TStringBuilder() | ||
|
@@ -5072,8 +5124,9 @@ bool TDiskRegistryState::HasDependentSsdDisks( | |
continue; | ||
} | ||
|
||
auto [allocating, deallocating] = PendingCleanup.FindDiskId(d.GetDeviceUUID()); | ||
if (d.GetPoolKind() == NProto::DEVICE_POOL_KIND_LOCAL && | ||
PendingCleanup.FindDiskId(d.GetDeviceUUID())) | ||
(allocating || deallocating)) | ||
{ | ||
return true; | ||
} | ||
|
@@ -5598,6 +5651,24 @@ auto TDiskRegistryState::FindDeviceLocation(const TDeviceId& deviceId) const | |
return const_cast<TDiskRegistryState*>(this)->FindDeviceLocation(deviceId); | ||
} | ||
|
||
auto TDiskRegistryState::FindDiskDevicesAgents(const TDiskState& disk) const | ||
-> std::set<const NProto::TAgentConfig*> | ||
{ | ||
std::set<TString> diskAgents; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. THashSet<> diskAgentIds |
||
for (const auto& uuid: disk.Devices) { | ||
// TODO: handle when not found | ||
diskAgents.insert(DeviceList.FindAgentId(uuid)); | ||
} | ||
|
||
std::set<const NProto::TAgentConfig*> agents; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. THashSet |
||
for (const auto& agentId: diskAgents) { | ||
// TODO: handle when not found | ||
agents.insert(AgentList.FindAgent(agentId)); | ||
} | ||
|
||
return std::move(agents); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. без move |
||
} | ||
|
||
auto TDiskRegistryState::FindDeviceLocation(const TDeviceId& deviceId) | ||
-> std::pair<NProto::TAgentConfig*, NProto::TDeviceConfig*> | ||
{ | ||
|
@@ -6354,7 +6425,9 @@ NProto::TDiskRegistryStateBackup TDiskRegistryState::BackupState() const | |
transform(GetDirtyDevices(), backup.MutableDirtyDevices(), [this] (auto& x) { | ||
NProto::TDiskRegistryStateBackup::TDirtyDevice dd; | ||
dd.SetId(x.GetDeviceUUID()); | ||
dd.SetDiskId(PendingCleanup.FindDiskId(x.GetDeviceUUID())); | ||
auto [allocating, deallocating] = PendingCleanup.FindDiskId(x.GetDeviceUUID()); // TODO: need to backup | ||
Y_UNUSED(allocating); | ||
dd.SetDiskId(*deallocating); | ||
|
||
return dd; | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
без move