| // 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 |