blob: 09718d9da601038d7bf074de4d73940d205c40a3 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <gtest/gtest.h>
#include "src/storage/lib/block_client/cpp/fake_block_device.h"
#include "src/storage/minfs/format.h"
#include "src/storage/minfs/fsck.h"
#include "src/storage/minfs/minfs_private.h"
namespace minfs {
namespace {
using block_client::FakeBlockDevice;
using block_client::FakeFVMBlockDevice;
constexpr uint64_t kBlockCount = 1 << 15;
constexpr uint32_t kBlockSize = 512;
TEST(FormatFilesystemTest, FilesystemFormatClearsJournal) {
auto device = std::make_unique<FakeBlockDevice>(kBlockCount, kBlockSize);
// Format the device.
auto bcache_or = Bcache::Create(std::move(device), kBlockCount);
ASSERT_TRUE(bcache_or.is_ok());
ASSERT_TRUE(Mkfs(bcache_or.value().get()).is_ok());
// Before re-formatting, fill the journal with sentinel pages.
auto superblock_or = LoadSuperblock(bcache_or.value().get());
ASSERT_TRUE(superblock_or.is_ok());
std::unique_ptr<uint8_t[]> sentinel(new uint8_t[kMinfsBlockSize]);
memset(sentinel.get(), 'a', kMinfsBlockSize);
storage::VmoBuffer buffer;
ASSERT_EQ(buffer.Initialize(bcache_or.value().get(), JournalBlocks(superblock_or.value()),
kMinfsBlockSize, "journal-buffer"),
ZX_OK);
for (size_t i = 0; i < JournalBlocks(superblock_or.value()); i++) {
memcpy(buffer.Data(i), sentinel.get(), kMinfsBlockSize);
}
storage::Operation operation = {};
operation.type = storage::OperationType::kWrite;
operation.vmo_offset = 0;
operation.dev_offset = JournalStartBlock(superblock_or.value());
operation.length = JournalBlocks(superblock_or.value());
ASSERT_EQ(bcache_or->RunOperation(operation, &buffer), ZX_OK);
// Format the device. We expect this to clear the sentinel pages.
ASSERT_TRUE(Mkfs(bcache_or.value().get()).is_ok());
// Verify the superblock has the correct versions.
auto new_superblock_or = LoadSuperblock(bcache_or.value().get());
ASSERT_TRUE(new_superblock_or.is_ok());
EXPECT_EQ(kMinfsCurrentMajorVersion, new_superblock_or->major_version);
EXPECT_EQ(kMinfsCurrentMinorVersion, new_superblock_or->oldest_minor_version);
// Verify that the device has written zeros to the expected location, overwriting the sentinel
// pages.
operation.type = storage::OperationType::kRead;
operation.vmo_offset = 0;
operation.dev_offset = JournalStartBlock(superblock_or.value());
operation.length = JournalBlocks(superblock_or.value());
ASSERT_EQ(bcache_or->RunOperation(operation, &buffer), ZX_OK);
std::unique_ptr<uint8_t[]> expected_buffer(new uint8_t[kMinfsBlockSize]);
memset(expected_buffer.get(), 0, kMinfsBlockSize);
for (size_t i = fs::kJournalMetadataBlocks; i < JournalBlocks(superblock_or.value()); i++) {
EXPECT_EQ(memcmp(buffer.Data(i), expected_buffer.get(), kMinfsBlockSize), 0);
}
}
} // namespace
} // namespace minfs