Skip to content

Commit 09f1070

Browse files
committed
detect and remove inconsistency on load
1 parent 65353b8 commit 09f1070

File tree

1 file changed

+69
-26
lines changed

1 file changed

+69
-26
lines changed

cloud/filestore/libs/vfs_fuse/directory_handles_storage.cpp

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -115,39 +115,82 @@ void TDirectoryHandlesStorage::ResetHandle(ui64 handleId)
115115

116116
void TDirectoryHandlesStorage::LoadHandles(TDirectoryHandleMap& handles)
117117
{
118-
TGuard guard(TableLock);
118+
struct TUpdateVersionInfo
119+
{
120+
ui64 LargestUpdateVersion = 0;
121+
ui64 ChunksCount = 0;
122+
bool IsFirstChunkPresented = false;
123+
};
124+
125+
TMap<ui64, TUpdateVersionInfo> updateVersionInfo;
126+
127+
{
128+
TGuard guard(TableLock);
129+
130+
for (auto it = Table->begin(); it != Table->end(); ++it) {
131+
TStringBuf record = *it;
132+
if (record.empty()) {
133+
STORAGE_TRACE(
134+
"bad record from storage during load directory handles");
135+
continue;
136+
}
119137

120-
for (auto it = Table->begin(); it != Table->end(); ++it) {
121-
TStringBuf record = *it;
122-
if (record.empty()) {
123-
STORAGE_TRACE(
124-
"bad record from storage during load directory handles");
125-
continue;
126-
}
138+
auto [handleId, chunk] = DeserializeHandleChunk(record);
139+
140+
if (!handleId) {
141+
STORAGE_DEBUG(
142+
"bad deserialize for record %lu from storage during load "
143+
"directory handles",
144+
it.GetIndex());
145+
continue;
146+
}
127147

128-
auto [handleId, chunk] = DeserializeHandleChunk(record);
148+
if (!handles.contains(handleId)) {
149+
handles[handleId] =
150+
std::make_shared<TDirectoryHandle>(chunk->Index);
151+
}
129152

130-
if (!handleId) {
131-
STORAGE_DEBUG(
132-
"bad deserialize for record %lu from storage during load "
133-
"directory handles",
134-
it.GetIndex());
135-
continue;
136-
}
153+
handles[handleId]->ConsumeChunk(*chunk);
137154

138-
if (!handles.contains(handleId)) {
139-
handles[handleId] =
140-
std::make_shared<TDirectoryHandle>(chunk->Index);
155+
updateVersionInfo[handleId].ChunksCount++;
156+
if (chunk->UpdateVersion >
157+
updateVersionInfo[handleId].LargestUpdateVersion)
158+
{
159+
updateVersionInfo[handleId].LargestUpdateVersion =
160+
chunk->UpdateVersion;
161+
}
162+
163+
if (chunk->UpdateVersion == 0) {
164+
updateVersionInfo[handleId].IsFirstChunkPresented = true;
165+
HandleIdToIndices[handleId].insert(
166+
HandleIdToIndices[handleId].begin(),
167+
it.GetIndex());
168+
} else {
169+
HandleIdToIndices[handleId].push_back(it.GetIndex());
170+
}
141171
}
172+
}
142173

143-
handles[handleId]->ConsumeChunk(*chunk);
174+
for (auto [handleId, updateVersionInfo]: updateVersionInfo) {
175+
if (!updateVersionInfo.IsFirstChunkPresented) {
176+
ReportDirectoryHandlesStorageError(
177+
TStringBuilder()
178+
<< "First chunk for handle " << handleId << " is missing");
144179

145-
if (chunk->UpdateVersion == 0) {
146-
HandleIdToIndices[handleId].insert(
147-
HandleIdToIndices[handleId].begin(),
148-
it.GetIndex());
149-
} else {
150-
HandleIdToIndices[handleId].push_back(it.GetIndex());
180+
RemoveHandle(handleId);
181+
continue;
182+
}
183+
184+
if (updateVersionInfo.ChunksCount !=
185+
updateVersionInfo.LargestUpdateVersion + 1)
186+
{
187+
ReportDirectoryHandlesStorageError(
188+
TStringBuilder()
189+
<< "Total chunks count " << updateVersionInfo.ChunksCount
190+
<< " is not equal to largest update version "
191+
<< updateVersionInfo.LargestUpdateVersion << " + 1");
192+
ResetHandle(handleId);
193+
continue;
151194
}
152195
}
153196
}

0 commit comments

Comments
 (0)