in src/prod/src/ktllogger/sys/tools/filefuzz/makeseed/makeseed.cpp [354:1168]
void MakeSeedFiles()
{
NTSTATUS status;
KSynchronizer activateSync;
KSynchronizer sync;
RvdLogManager::SPtr logManager;
//
// Get a log manager
//
status = RvdLogManager::Create(KTL_TAG_LOGGER, KtlSystem::GlobalNonPagedAllocator(), logManager);
VERIFY_IS_TRUE(NT_SUCCESS(status));
status = logManager->Activate(nullptr, activateSync);
VERIFY_IS_TRUE(K_ASYNC_SUCCESS(status));
status = logManager->RegisterVerificationCallback(KLogicalLogInformation::GetLogicalLogStreamType(),
&VerifyRecordCallback);
VERIFY_IS_TRUE(NT_SUCCESS(status));
//
// Test file 1: Create empty log file with a single stream
//
{
KStringView fileName(L"\\??\\c:\\seeds\\Container.log");
RvdLog::SPtr log;
KGuid logGuid;
RvdLogStream::SPtr logStream;
KGuid logStreamGuid;
logGuid = WellKnownGuid2;
CreateLogFile(*logManager,
fileName,
logGuid,
log,
16 * 1024, // MaxRecordSize
256 * 1024, // LogSize
2); // NumberStreams
CreateLogStream(*log,
logStreamGuid,
logStream);
log = nullptr;
logStream = nullptr;
}
//
// Seed file 1: Create empty log file with a single stream
//
{
KStringView fileName(L"\\??\\c:\\seeds\\EmptyLog.log");
RvdLog::SPtr log;
KGuid logGuid;
RvdLogStream::SPtr logStream;
KGuid logStreamGuid;
logGuid = WellKnownGuid;
CreateLogFile(*logManager,
fileName,
logGuid,
log,
16 * 1024, // MaxRecordSize
256 * 1024, // LogSize
2); // NumberStreams
CreateLogStream(*log,
logStreamGuid,
logStream);
log = nullptr;
logStream = nullptr;
}
//
// Seed file 2: Log file with logical log record in metadata only
//
{
KStringView fileName(L"\\??\\c:\\seeds\\MetadataOnly.log");
RvdLog::SPtr log;
KGuid logGuid;
RvdLogStream::SPtr logStream;
KGuid logStreamGuid;
ULONG dataSize = 500;
KBuffer::SPtr dataBuffer;
PUCHAR p;
status = KBuffer::Create(dataSize, dataBuffer, *g_Allocator);
VERIFY_IS_TRUE(NT_SUCCESS(status));
p = static_cast<PUCHAR>(dataBuffer->GetBuffer());
srand((ULONG)GetTickCount());
for (ULONG i = 0; i < dataSize; i++)
{
p[i] = static_cast<UCHAR>(rand() % 255);
}
logGuid = WellKnownGuid;
CreateLogFile(*logManager,
fileName,
logGuid,
log,
16 * 1024, // MaxRecordSize
256 * 1024, // LogSize
2); // NumberStreams
CreateLogStream(*log,
logStreamGuid,
logStream);
ULONGLONG asn;
ULONGLONG version;
asn = RvdLogAsn::Min().Get();;
version = 0;
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
0);
VERIFY_IS_TRUE(NT_SUCCESS(status));
asn += dataBuffer->QuerySize();
log = nullptr;
logStream = nullptr;
}
//
// Seed file 3: Log file with logical log record in metadata and
// data only
//
{
KStringView fileName(L"\\??\\c:\\seeds\\MetadataAndData.log");
RvdLog::SPtr log;
KGuid logGuid;
RvdLogStream::SPtr logStream;
KGuid logStreamGuid;
const ULONG dataSize = 5000;
KBuffer::SPtr dataBuffer;
PUCHAR p;
status = KBuffer::Create(dataSize, dataBuffer, *g_Allocator);
VERIFY_IS_TRUE(NT_SUCCESS(status));
p = static_cast<PUCHAR>(dataBuffer->GetBuffer());
srand((ULONG)GetTickCount());
for (ULONG i = 0; i < dataSize; i++)
{
p[i] = static_cast<UCHAR>(rand() % 255);
}
logGuid = WellKnownGuid;
CreateLogFile(*logManager,
fileName,
logGuid,
log,
16 * 1024, // MaxRecordSize
256 * 1024, // LogSize
2); // NumberStreams
CreateLogStream(*log,
logStreamGuid,
logStream);
ULONGLONG asn;
ULONGLONG version;
asn = RvdLogAsn::Min().Get();;
version = 0;
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
0);
VERIFY_IS_TRUE(NT_SUCCESS(status));
asn += dataBuffer->QuerySize();
log = nullptr;
logStream = nullptr;
}
//
// Seed file 4: Log file with logical log records that are metadata
// only and metadata and data
//
{
KStringView fileName(L"\\??\\c:\\seeds\\ManyRecords.log");
RvdLog::SPtr log;
KGuid logGuid;
RvdLogStream::SPtr logStream;
KGuid logStreamGuid;
const ULONG dataSizeMD = 5000;
const ULONG dataSizeMO = 500;
KBuffer::SPtr dataBufferMD;
KBuffer::SPtr dataBufferMO;
PUCHAR p;
status = KBuffer::Create(dataSizeMD, dataBufferMD, *g_Allocator);
VERIFY_IS_TRUE(NT_SUCCESS(status));
p = static_cast<PUCHAR>(dataBufferMD->GetBuffer());
srand((ULONG)GetTickCount());
for (ULONG i = 0; i < dataSizeMD; i++)
{
p[i] = static_cast<UCHAR>(rand() % 255);
}
status = KBuffer::Create(dataSizeMO, dataBufferMO, *g_Allocator);
VERIFY_IS_TRUE(NT_SUCCESS(status));
p = static_cast<PUCHAR>(dataBufferMO->GetBuffer());
srand((ULONG)GetTickCount());
for (ULONG i = 0; i < dataSizeMO; i++)
{
p[i] = static_cast<UCHAR>(rand() % 255);
}
logGuid = WellKnownGuid;
CreateLogFile(*logManager,
fileName,
logGuid,
log,
16 * 1024, // MaxRecordSize
256 * 1024, // LogSize
2); // NumberStreams
CreateLogStream(*log,
logStreamGuid,
logStream);
ULONGLONG asn;
ULONGLONG version;
asn = RvdLogAsn::Min().Get();;
version = 0;
for (ULONG i = 0; i < 7; i++)
{
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBufferMO,
0);
VERIFY_IS_TRUE(NT_SUCCESS(status));
asn += dataBufferMO->QuerySize();
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBufferMD,
0);
VERIFY_IS_TRUE(NT_SUCCESS(status));
asn += dataBufferMD->QuerySize();
}
log = nullptr;
logStream = nullptr;
}
//
// Seed file 5: Create a log file that has missing records in the
// region of chaos
{
KStringView fileName(L"\\??\\c:\\seeds\\ChaosRegion.log");
RvdLog::SPtr log;
KGuid logGuid;
RvdLogStream::SPtr logStream;
KGuid logStreamGuid;
const ULONG dataSizeMD = 5000;
const ULONG dataSizeMO = 500;
KBuffer::SPtr dataBufferMD;
KBuffer::SPtr dataBufferMO;
PUCHAR p;
status = KBuffer::Create(dataSizeMD, dataBufferMD, *g_Allocator);
VERIFY_IS_TRUE(NT_SUCCESS(status));
p = static_cast<PUCHAR>(dataBufferMD->GetBuffer());
srand((ULONG)GetTickCount());
for (ULONG i = 0; i < dataSizeMD; i++)
{
p[i] = static_cast<UCHAR>(rand() % 255);
}
status = KBuffer::Create(dataSizeMO, dataBufferMO, *g_Allocator);
VERIFY_IS_TRUE(NT_SUCCESS(status));
p = static_cast<PUCHAR>(dataBufferMO->GetBuffer());
srand((ULONG)GetTickCount());
for (ULONG i = 0; i < dataSizeMO; i++)
{
p[i] = static_cast<UCHAR>(rand() % 255);
}
logGuid = WellKnownGuid;
CreateLogFile(*logManager,
fileName,
logGuid,
log,
16 * 1024, // MaxRecordSize
256 * 1024, // LogSize
2); // NumberStreams
CreateLogStream(*log,
logStreamGuid,
logStream);
ULONGLONG asn;
ULONGLONG version;
asn = RvdLogAsn::Min().Get();;
version = 0;
for (ULONG i = 0; i < 7; i++)
{
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBufferMO,
0);
VERIFY_IS_TRUE(NT_SUCCESS(status));
asn += dataBufferMO->QuerySize();
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBufferMD,
0);
VERIFY_IS_TRUE(NT_SUCCESS(status));
asn += dataBufferMD->QuerySize();
}
log = nullptr;
logStream = nullptr;
//
// Manually overwrite a few records
//
KBlockFile::SPtr blockFile;
KWString fileNameString(*g_Allocator);
fileNameString = (PWCHAR)fileName;
KIoBuffer::SPtr zeroBuffer;
PVOID pv;
status = KIoBuffer::CreateSimple(fourKB, zeroBuffer, pv, *g_Allocator);
VERIFY_IS_TRUE(NT_SUCCESS(status));
p = static_cast<PUCHAR>(pv);
for (ULONG i = 0; i < fourKB; i++)
{
p[i] = 0;
}
status = KBlockFile::Create(fileNameString,
FALSE,
KBlockFile::eOpenExisting,
blockFile,
sync,
nullptr,
*g_Allocator);
VERIFY_IS_TRUE(NT_SUCCESS(status));
status = sync.WaitForCompletion();
VERIFY_IS_TRUE(NT_SUCCESS(status));
//
// Log should look like this and so we will remove record as
// LSN 15000 to force data in region of chaos
//
// --LC 0 length 1000 expectnext: 1000 HIGHLSN: FFFFFFFFFFFFFFFF CHKPTLSN: FFFFFFFFFFFFFFFF PREVLSN: FFFFFFFFFFFFFFFF Asn: 1 Version: -1
// --LR 1000 length 1000 expectnext: 2000 highlsn: 0 chkptlsn: 0 PREVLSN: FFFFFFFFFFFFFFFF Asn: 1 Version: 1
// ---S 2000 length 1000 expectnext: 3000 highlsn: 0 chkptlsn: 0 prevlsn: 1000 Asn: 1 Version: -1
// ---R 3000 length 2000 expectnext: 5000 highlsn: 2000 chkptlsn: 0 prevlsn: 2000 Asn: 501 Version: 2
// ---R 5000 length 1000 expectnext: 6000 highlsn: 3000 chkptlsn: 0 prevlsn: 3000 Asn: 5501 Version: 3
// ---R 6000 length 2000 expectnext: 8000 highlsn: 5000 chkptlsn: 0 prevlsn: 5000 Asn: 6001 Version: 4
// ---R 8000 length 1000 expectnext: 9000 highlsn: 6000 chkptlsn: 0 prevlsn: 6000 Asn: 11001 Version: 5
// ---R 9000 length 2000 expectnext: b000 highlsn: 8000 chkptlsn: 0 prevlsn: 8000 Asn: 11501 Version: 6
// ---R b000 length 1000 expectnext: c000 highlsn: 9000 chkptlsn: 0 prevlsn: 9000 Asn: 16501 Version: 7
// ---R c000 length 2000 expectnext: e000 highlsn: b000 chkptlsn: 0 prevlsn: b000 Asn: 17001 Version: 8
// ---R e000 length 1000 expectnext: f000 highlsn: c000 chkptlsn: 0 prevlsn: c000 Asn: 22001 Version: 9
// ---R f000 length 2000 expectnext: 11000 highlsn: e000 chkptlsn: 0 prevlsn: e000 Asn: 22501 Version: 10
// ---C 11000 length 1000 expectnext: 12000 highlsn: e000 chkptlsn: 0 prevlsn: 0 Asn: 1 Version: -1
// ---R 12000 length 1000 expectnext: 13000 highlsn: 11000 chkptlsn: 11000 prevlsn: f000 Asn: 27501 Version: 11
// ---R 13000 length 2000 expectnext: 15000 highlsn: 12000 chkptlsn: 11000 prevlsn: 12000 Asn: 28001 Version: 12
// ---R 15000 length 1000 expectnext: 16000 highlsn: 13000 chkptlsn: 11000 prevlsn: 13000 Asn: 33001 Version: 13
// ---R 16000 length 2000 expectnext: 18000 highlsn: 15000 chkptlsn: 11000 prevlsn: 15000 Asn: 33501 Version: 14
//
status = blockFile->Transfer(KBlockFile::IoPriority::eForeground,
KBlockFile::TransferType::eWrite,
0x16000,
*zeroBuffer,
sync);
VERIFY_IS_TRUE(NT_SUCCESS(status));
status = sync.WaitForCompletion();
VERIFY_IS_TRUE(NT_SUCCESS(status));
blockFile->Close();
}
//
// Seed file 6: Log file with logical log records that are metadata
// only and metadata and data and wrapped around
//
{
KStringView fileName(L"\\??\\c:\\seeds\\Wrapped.log");
RvdLog::SPtr log;
KGuid logGuid;
RvdLogStream::SPtr logStream;
KGuid logStreamGuid;
const ULONG dataSizeMD = 5000;
const ULONG dataSizeMO = 500;
KBuffer::SPtr dataBufferMD;
KBuffer::SPtr dataBufferMO;
PUCHAR p;
status = KBuffer::Create(dataSizeMD, dataBufferMD, *g_Allocator);
VERIFY_IS_TRUE(NT_SUCCESS(status));
p = static_cast<PUCHAR>(dataBufferMD->GetBuffer());
srand((ULONG)GetTickCount());
for (ULONG i = 0; i < dataSizeMD; i++)
{
p[i] = static_cast<UCHAR>(rand() % 255);
}
status = KBuffer::Create(dataSizeMO, dataBufferMO, *g_Allocator);
VERIFY_IS_TRUE(NT_SUCCESS(status));
p = static_cast<PUCHAR>(dataBufferMO->GetBuffer());
srand((ULONG)GetTickCount());
for (ULONG i = 0; i < dataSizeMO; i++)
{
p[i] = static_cast<UCHAR>(rand() % 255);
}
logGuid = WellKnownGuid;
CreateLogFile(*logManager,
fileName,
logGuid,
log,
16 * 1024, // MaxRecordSize
256 * 1024, // LogSize
2); // NumberStreams
CreateLogStream(*log,
logStreamGuid,
logStream);
ULONGLONG asn;
ULONGLONG version;
asn = RvdLogAsn::Min().Get();;
version = 0;
for (ULONG j = 0; j < 64; j++)
{
logStream->Truncate(asn, asn);
for (ULONG i = 0; i < 7; i++)
{
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBufferMO,
0);
VERIFY_IS_TRUE(NT_SUCCESS(status));
asn += dataBufferMO->QuerySize();
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBufferMD,
0);
VERIFY_IS_TRUE(NT_SUCCESS(status));
asn += dataBufferMD->QuerySize();
}
}
log = nullptr;
logStream = nullptr;
}
//
// Seed file 7: Log file with randomly sized logical log records that are metadata
// only and metadata and data and at a log full
// condition
//
{
KStringView fileName(L"\\??\\c:\\seeds\\Logfull.log");
RvdLog::SPtr log;
KGuid logGuid;
RvdLogStream::SPtr logStream;
KGuid logStreamGuid;
const ULONG maxDataSize = 12 * 1024;
KBuffer::SPtr dataBuffer;
PUCHAR p;
status = KBuffer::Create(maxDataSize, dataBuffer, *g_Allocator);
VERIFY_IS_TRUE(NT_SUCCESS(status));
p = static_cast<PUCHAR>(dataBuffer->GetBuffer());
srand((ULONG)GetTickCount());
for (ULONG i = 0; i < maxDataSize; i++)
{
p[i] = static_cast<UCHAR>(rand() % 255);
}
logGuid = WellKnownGuid;
CreateLogFile(*logManager,
fileName,
logGuid,
log,
16 * 1024, // MaxRecordSize
256 * 1024, // LogSize
2); // NumberStreams
CreateLogStream(*log,
logStreamGuid,
logStream);
ULONGLONG asn;
ULONGLONG version;
asn = RvdLogAsn::Min().Get();;
version = 0;
ULONG dataWritten;
status = STATUS_SUCCESS;
while (NT_SUCCESS(status))
{
dataWritten = (rand() % 5000);
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
dataWritten);
VERIFY_IS_TRUE((status == STATUS_LOG_FULL) || (NT_SUCCESS(status)));
asn += dataWritten;
}
log = nullptr;
logStream = nullptr;
}
//
// Seed file 8: Log file with that has tail truncation
//
{
KStringView fileName(L"\\??\\c:\\seeds\\TailTruncate.log");
RvdLog::SPtr log;
KGuid logGuid;
RvdLogStream::SPtr logStream;
KGuid logStreamGuid;
const ULONG maxDataSize = 12 * 1024;
KBuffer::SPtr dataBuffer;
PUCHAR p;
status = KBuffer::Create(maxDataSize, dataBuffer, *g_Allocator);
VERIFY_IS_TRUE(NT_SUCCESS(status));
p = static_cast<PUCHAR>(dataBuffer->GetBuffer());
srand((ULONG)GetTickCount());
for (ULONG i = 0; i < maxDataSize; i++)
{
p[i] = static_cast<UCHAR>(rand() % 255);
}
logGuid = WellKnownGuid;
CreateLogFile(*logManager,
fileName,
logGuid,
log,
16 * 1024, // MaxRecordSize
256 * 1024, // LogSize
2); // NumberStreams
CreateLogStream(*log,
logStreamGuid,
logStream);
ULONGLONG asn;
ULONGLONG version;
asn = RvdLogAsn::Min().Get();;
version = 0;
ULONG dataWritten;
{
dataWritten = 500;
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
dataWritten);
VERIFY_IS_TRUE((status == STATUS_LOG_FULL) || (NT_SUCCESS(status)));
asn += dataWritten;
}
asn -= 200;
{
dataWritten = 500;
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
dataWritten);
VERIFY_IS_TRUE((status == STATUS_LOG_FULL) || (NT_SUCCESS(status)));
asn += dataWritten;
}
{
dataWritten = 7325;
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
dataWritten);
VERIFY_IS_TRUE((status == STATUS_LOG_FULL) || (NT_SUCCESS(status)));
asn += dataWritten;
}
asn -= 5419;
{
dataWritten = 5000;
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
dataWritten);
VERIFY_IS_TRUE((status == STATUS_LOG_FULL) || (NT_SUCCESS(status)));
asn += dataWritten;
}
{
dataWritten = 500;
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
dataWritten);
VERIFY_IS_TRUE((status == STATUS_LOG_FULL) || (NT_SUCCESS(status)));
asn += dataWritten;
}
{
dataWritten = 500;
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
dataWritten);
VERIFY_IS_TRUE((status == STATUS_LOG_FULL) || (NT_SUCCESS(status)));
asn += dataWritten;
}
{
dataWritten = 500;
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
dataWritten);
VERIFY_IS_TRUE((status == STATUS_LOG_FULL) || (NT_SUCCESS(status)));
asn += dataWritten;
}
{
dataWritten = 500;
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
dataWritten);
VERIFY_IS_TRUE((status == STATUS_LOG_FULL) || (NT_SUCCESS(status)));
asn += dataWritten;
}
asn -= 1234;
{
dataWritten = 500;
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
dataWritten);
VERIFY_IS_TRUE((status == STATUS_LOG_FULL) || (NT_SUCCESS(status)));
asn += dataWritten;
}
log = nullptr;
logStream = nullptr;
}
//
// Seed file 9: Data at the very end of the log
//
{
KStringView fileName(L"\\??\\c:\\seeds\\AtEnd.log");
RvdLog::SPtr log;
KGuid logGuid;
RvdLogStream::SPtr logStream;
KGuid logStreamGuid;
const ULONG maxDataSize = 5 * 1024;
KBuffer::SPtr dataBuffer;
PUCHAR p;
status = KBuffer::Create(maxDataSize, dataBuffer, *g_Allocator);
VERIFY_IS_TRUE(NT_SUCCESS(status));
p = static_cast<PUCHAR>(dataBuffer->GetBuffer());
srand((ULONG)GetTickCount());
for (ULONG i = 0; i < maxDataSize; i++)
{
p[i] = static_cast<UCHAR>(rand() % 255);
}
logGuid = WellKnownGuid;
CreateLogFile(*logManager,
fileName,
logGuid,
log,
16 * 1024, // MaxRecordSize
256 * 1024, // LogSize
2); // NumberStreams
CreateLogStream(*log,
logStreamGuid,
logStream);
ULONGLONG asn;
ULONGLONG version;
asn = RvdLogAsn::Min().Get();;
version = 0;
status = STATUS_SUCCESS;
while (NT_SUCCESS(status))
{
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
0);
if (NT_SUCCESS(status))
{
asn += dataBuffer->QuerySize();
}
}
VERIFY_IS_TRUE(status == STATUS_LOG_FULL);
RvdLogAsn truncationAsn = 12000;
logStream->Truncate(truncationAsn, truncationAsn);
version++;
status = WriteLogicalLogRecord(*log,
*logStream,
version,
asn,
*dataBuffer,
500);
asn += dataBuffer->QuerySize();
log = nullptr;
logStream = nullptr;
}
logManager->Deactivate();
activateSync.WaitForCompletion();
logManager.Reset();
}