DiskWriteDriver: Remove use of atomic buffer

This commit is contained in:
Emily Brooks
2022-12-02 00:09:49 +00:00
committed by Kyle Schwarz
parent c97db0f35f
commit ed1632c652
8 changed files with 16 additions and 125 deletions
+1 -13
View File
@@ -40,7 +40,7 @@ public:
}
std::optional<uint64_t> writeLogicalDiskAligned(Communication&, device_eventhandler_t report, uint64_t pos,
const uint8_t* atomicBuf, const uint8_t* from, uint64_t amount, std::chrono::milliseconds) override {
const uint8_t* from, uint64_t amount, std::chrono::milliseconds) override {
writeCalls++;
EXPECT_EQ(pos % getBlockSizeBounds().first, 0); // Ensure the alignment rules are respected
@@ -52,16 +52,6 @@ public:
std::optional<uint64_t> writeAmount = std::min(amount, mockDisk.size() - pos);
if(writeAmount > 0u) {
if(atomicBuf) {
if(supportsAtomic) {
atomicityChecks++;
if(memcmp(mockDisk.data() + pos, atomicBuf, static_cast<size_t>(*writeAmount)))
return RetryAtomic; // Atomic check failed
} else {
report(APIEvent::Type::AtomicOperationCompletedNonatomically, NonatomicSeverity);
}
}
memcpy(mockDisk.data() + pos, from, static_cast<size_t>(*writeAmount));
}
return writeAmount;
@@ -70,8 +60,6 @@ public:
std::array<uint8_t, 1024> mockDisk;
size_t readCalls = 0;
size_t writeCalls = 0;
size_t atomicityChecks = 0;
bool supportsAtomic = true; // Ability to simulate a driver that doesn't support atomic writes
std::function<void(void)> afterReadHook;
private:
+1 -55
View File
@@ -7,7 +7,6 @@ TEST_F(DiskDriverTest, Write) {
EXPECT_STREQ(reinterpret_cast<char*>(driver->mockDisk.data()), TEST_OVERWRITE_STRING);
EXPECT_EQ(driver->mockDisk[sizeof(TEST_OVERWRITE_STRING) + 1], TEST_STRING[sizeof(TEST_OVERWRITE_STRING) + 1]);
EXPECT_EQ(driver->mockDisk[126], 126u);
EXPECT_EQ(driver->atomicityChecks, 1u);
EXPECT_EQ(driver->readCalls, 1u);
EXPECT_EQ(driver->writeCalls, 1u);
}
@@ -18,25 +17,10 @@ TEST_F(DiskDriverTest, WriteZero) {
EXPECT_TRUE(amountWritten.has_value());
EXPECT_EQ(amountWritten, 0u);
EXPECT_EQ(driver->mockDisk[0], TEST_STRING[0]);
EXPECT_EQ(driver->atomicityChecks, 0u);
EXPECT_EQ(driver->readCalls, 0u);
EXPECT_EQ(driver->writeCalls, 0u);
}
TEST_F(DiskDriverTest, WriteNoAtomicityCheck) {
driver->supportsAtomic = false;
expectedErrors.push({ APIEvent::Type::AtomicOperationCompletedNonatomically, APIEvent::Severity::EventInfo });
const auto amountWritten = writeLogicalDisk(0u, reinterpret_cast<const uint8_t*>(TEST_OVERWRITE_STRING), sizeof(TEST_OVERWRITE_STRING));
EXPECT_TRUE(amountWritten.has_value());
EXPECT_EQ(amountWritten, sizeof(TEST_OVERWRITE_STRING));
EXPECT_STREQ(reinterpret_cast<char*>(driver->mockDisk.data()), TEST_OVERWRITE_STRING);
EXPECT_EQ(driver->mockDisk[sizeof(TEST_OVERWRITE_STRING) + 1], TEST_STRING[sizeof(TEST_OVERWRITE_STRING) + 1]);
EXPECT_EQ(driver->mockDisk[126], 126u);
EXPECT_EQ(driver->atomicityChecks, 0u);
EXPECT_EQ(driver->readCalls, 1u);
EXPECT_EQ(driver->writeCalls, 1u);
}
TEST_F(DiskDriverTest, WriteUnaligned) {
const auto amountWritten = writeLogicalDisk(3, reinterpret_cast<const uint8_t*>(TEST_OVERWRITE_STRING), sizeof(TEST_OVERWRITE_STRING));
EXPECT_TRUE(amountWritten.has_value());
@@ -44,7 +28,6 @@ TEST_F(DiskDriverTest, WriteUnaligned) {
EXPECT_EQ(driver->mockDisk[0], TEST_STRING[0]);
EXPECT_EQ(driver->mockDisk[5], TEST_OVERWRITE_STRING[2]);
EXPECT_EQ(driver->mockDisk[110], 110u);
EXPECT_EQ(driver->atomicityChecks, 1u);
EXPECT_EQ(driver->readCalls, 1u);
EXPECT_EQ(driver->writeCalls, 1u);
}
@@ -58,46 +41,10 @@ TEST_F(DiskDriverTest, WriteUnalignedLong) {
EXPECT_EQ(amountWritten, buf.size());
EXPECT_EQ(driver->mockDisk[0], TEST_STRING[0]);
EXPECT_EQ(driver->mockDisk[330], ((buf.size() - 30) + 20) & 0xFF);
EXPECT_EQ(driver->atomicityChecks, 3u);
EXPECT_EQ(driver->readCalls, 3u);
EXPECT_EQ(driver->readCalls, 2u);
EXPECT_EQ(driver->writeCalls, 3u);
}
TEST_F(DiskDriverTest, WriteUnalignedLongAtomicityFailures) {
std::array<uint8_t, 500> buf;
for(size_t i = 0; i < buf.size(); i++)
buf[i] = static_cast<uint8_t>((buf.size() - i) + 20);
for(int i = 0; i < 4; i++)
expectedErrors.push({ APIEvent::Type::AtomicOperationRetried, APIEvent::Severity::EventInfo });
int i = 0;
driver->afterReadHook = [&i, this]() {
switch(i) {
case 0: driver->mockDisk[295] = uint8_t(0xCD); break;
case 1: break; // We don't mess with this one so the first block can be written
case 2: driver->mockDisk[600] = uint8_t(0xDC); break;
case 3: driver->mockDisk[602] = uint8_t(0xDC); break;
case 4: break; // We don't mess with this one so the second block can be written
case 5: driver->mockDisk[777] = uint8_t(0x22); break;
case 6: break; // We don't mess with this one so the third block can be written
}
i++;
};
const auto amountWritten = writeLogicalDisk(300, buf.data(), buf.size());
EXPECT_TRUE(amountWritten.has_value());
EXPECT_EQ(amountWritten, buf.size());
EXPECT_EQ(driver->mockDisk[0], TEST_STRING[0]);
EXPECT_EQ(driver->mockDisk[295], 0xCDu); // If the atomic worked correctly this write won't have gotten trampled
// Our writes happen after both of these, so they overwrite the 0xDC values
EXPECT_EQ(driver->mockDisk[600], ((buf.size() - 300) + 20) & 0xFF);
EXPECT_EQ(driver->mockDisk[602], ((buf.size() - 302) + 20) & 0xFF);
EXPECT_EQ(driver->atomicityChecks, 7u);
EXPECT_EQ(driver->readCalls, 7u);
EXPECT_EQ(driver->writeCalls, 7u);
}
TEST_F(DiskDriverTest, WritePastEnd) {
expectedErrors.push({ APIEvent::Type::EOFReached, APIEvent::Severity::Error });
const auto amountWritten = writeLogicalDisk(1020, reinterpret_cast<const uint8_t*>(TEST_OVERWRITE_STRING), sizeof(TEST_OVERWRITE_STRING));
@@ -114,7 +61,6 @@ TEST_F(DiskDriverTest, WriteBadStartingPos) {
expectedErrors.push({ APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error });
const auto amountWritten = writeLogicalDisk(2000, reinterpret_cast<const uint8_t*>(TEST_OVERWRITE_STRING), sizeof(TEST_OVERWRITE_STRING));
EXPECT_FALSE(amountWritten.has_value());
EXPECT_EQ(driver->atomicityChecks, 0u);
EXPECT_EQ(driver->readCalls, 1u);
EXPECT_EQ(driver->writeCalls, 0u); // We never even attempt the write
}