blob: c11ede6884ff182de1bed9fb54ed8b7e9e6ab65f [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 <fvm/format.h>
#include <zxtest/zxtest.h>
#include "utils.h"
namespace fvm {
namespace {
// Shared constants for all resize tests.
constexpr uint64_t kBlockSize = 512;
constexpr uint64_t kSliceSize = 1 << 20;
constexpr uint64_t kDataSizeInBlocks = 10;
constexpr uint64_t kDataSize = kBlockSize * kDataSizeInBlocks;
constexpr char kPartitionName[] = "partition-name";
constexpr uint8_t kPartitionUniqueGuid[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
constexpr uint8_t kPartitionTypeGuid[] = {0xAA, 0xFF, 0xBB, 0x00, 0x33, 0x44, 0x88, 0x99,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
constexpr uint64_t kPartitionSliceCount = 1;
TEST(FvmResizeTest, NonPreallocatedMetadataIsUnaffected) {
constexpr uint64_t kInitialBlockCount = (50 * kSliceSize) / kBlockSize;
constexpr uint64_t kMaxBlockCount = (4 << 10) * kSliceSize / kBlockSize;
unsigned int initial_seed = zxtest::Runner::GetInstance()->options().seed;
std::unique_ptr<RamdiskRef> ramdisk = RamdiskRef::Create(kBlockSize, kInitialBlockCount);
ASSERT_TRUE(ramdisk);
std::unique_ptr<FvmAdapter> fvm =
FvmAdapter::Create(kBlockSize, kInitialBlockCount, kSliceSize, ramdisk.get());
ASSERT_TRUE(fvm);
std::unique_ptr<VPartitionAdapter> vpartition = nullptr;
ASSERT_OK(fvm->AddPartition(kPartitionName, Guid(kPartitionUniqueGuid),
Guid(kPartitionTypeGuid), kPartitionSliceCount, &vpartition),
"Failed to add partition.");
ASSERT_TRUE(vpartition);
// Get current state of the FVM.
VolumeInfo before_grow_info;
ASSERT_OK(fvm->Query(&before_grow_info));
ASSERT_EQ(kSliceSize, before_grow_info.slice_size);
ASSERT_EQ(kPartitionSliceCount, before_grow_info.pslice_allocated_count);
auto random_data = MakeRandomBuffer(kDataSize, &initial_seed);
ASSERT_NO_FATAL_FAILURES(vpartition->WriteAt(random_data, 0));
// Grow the Device.
ASSERT_OK(ramdisk->Grow(kBlockSize * kMaxBlockCount));
// Rebind FVM and get a new connection to the vpartitions when they become available.
ASSERT_OK(fvm->Rebind({vpartition.get()}));
// Get stats after growth.
VolumeInfo after_grow_info;
ASSERT_OK(fvm->Query(&after_grow_info));
ASSERT_TRUE(IsConsistentAfterGrowth(before_grow_info, after_grow_info));
ASSERT_BYTES_EQ(&before_grow_info, &after_grow_info, sizeof(VolumeInfo));
// Data should still be present.
ASSERT_NO_FATAL_FAILURES(vpartition->CheckContentsAt(random_data, 0));
}
TEST(FvmResizeTest, PreallocatedMetadataGrowsCorrectly) {
constexpr uint64_t kInitialBlockCount = (50 * kSliceSize) / kBlockSize;
constexpr uint64_t kMaxBlockCount = (4 << 10) * kSliceSize / kBlockSize;
unsigned int initial_seed = zxtest::Runner::GetInstance()->options().seed;
std::unique_ptr<RamdiskRef> ramdisk = RamdiskRef::Create(kBlockSize, kInitialBlockCount);
ASSERT_TRUE(ramdisk);
std::unique_ptr<FvmAdapter> fvm = FvmAdapter::CreateGrowable(kBlockSize, kInitialBlockCount,
kMaxBlockCount, kSliceSize, ramdisk.get());
ASSERT_TRUE(fvm);
std::unique_ptr<VPartitionAdapter> vpartition = nullptr;
ASSERT_OK(fvm->AddPartition(kPartitionName, static_cast<Guid>(kPartitionUniqueGuid),
static_cast<Guid>(kPartitionTypeGuid), kPartitionSliceCount,
&vpartition),
"Failed to add partition.");
ASSERT_TRUE(vpartition);
// Expected metadata info.
FormatInfo final_format_info =
FormatInfo::FromDiskSize(kMaxBlockCount * kBlockSize, kSliceSize);
// Get current state of the FVM.
VolumeInfo before_grow_info;
ASSERT_OK(fvm->Query(&before_grow_info));
ASSERT_EQ(kSliceSize, before_grow_info.slice_size);
ASSERT_EQ(kPartitionSliceCount, before_grow_info.pslice_allocated_count);
auto random_data = MakeRandomBuffer(kDataSize, &initial_seed);
ASSERT_NO_FATAL_FAILURES(vpartition->WriteAt(random_data, 0));
// Grow the Device.
ASSERT_OK(ramdisk->Grow(kBlockSize * kMaxBlockCount));
// Rebind FVM and get a new connection to the vpartitions when they become available.
ASSERT_OK(fvm->Rebind({vpartition.get()}));
// Get stats after growth.
VolumeInfo after_grow_info;
ASSERT_OK(fvm->Query(&after_grow_info));
ASSERT_TRUE(IsConsistentAfterGrowth(before_grow_info, after_grow_info));
// Check that new slices are available
ASSERT_EQ(final_format_info.slice_count(), after_grow_info.pslice_total_count);
// Data should still be persisted.
ASSERT_NO_FATAL_FAILURES(vpartition->CheckContentsAt(random_data, 0));
// Verify new slices can be allocated, written to and read from.
ASSERT_OK(vpartition->Extend(kPartitionSliceCount,
after_grow_info.pslice_total_count - kPartitionSliceCount));
auto random_data_2 = MakeRandomBuffer(kDataSize, &initial_seed);
uint64_t offset = (final_format_info.slice_count() - 1) * kSliceSize;
ASSERT_NO_FATAL_FAILURES(vpartition->WriteAt(random_data_2, offset));
ASSERT_NO_FATAL_FAILURES(vpartition->CheckContentsAt(random_data_2, offset));
}
} // namespace
} // namespace fvm