blob: d884aa6d15b54042e369522bcbc97abb12393801 [file] [log] [blame]
// Copyright 2022 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 "src/storage/bin/start-storage-benchmark/block-device.h"
#include <fcntl.h>
#include <fidl/fuchsia.hardware.block.volume/cpp/wire.h>
#include <lib/fdio/fd.h>
#include <lib/service/llcpp/service.h>
#include <fbl/unique_fd.h>
#include <gtest/gtest.h>
#include "src/lib/storage/fs_management/cpp/format.h"
#include "src/lib/testing/predicates/status.h"
#include "src/storage/testing/fvm.h"
#include "src/storage/testing/ram_disk.h"
namespace storage_benchmark {
namespace {
constexpr uint64_t kBlockSize = 8192;
constexpr uint64_t kBlockCount = 512;
constexpr uint64_t kFvmSliceSize = 32lu * 1024;
constexpr uint64_t kVolumeSize = 0;
TEST(BlockDeviceTest, ConnectToFvmReturnsAValidConnection) {
auto ramdisk = storage::RamDisk::Create(kBlockSize, kBlockCount);
ASSERT_OK(ramdisk.status_value());
auto fvm_path = storage::CreateFvmInstance(ramdisk->path(), kFvmSliceSize);
ASSERT_OK(fvm_path.status_value());
auto fvm_client = ConnectToFvm(ramdisk->path());
ASSERT_OK(fvm_client.status_value());
auto fvm_info = fidl::WireCall(*fvm_client)->GetInfo();
ASSERT_OK(fvm_info.status());
ASSERT_OK(fvm_info.value().status);
EXPECT_EQ(fvm_info.value().info->slice_size, kFvmSliceSize);
}
TEST(BlockDeviceTest, FvmVolumeCreateWorks) {
auto ramdisk = storage::RamDisk::Create(kBlockSize, kBlockCount);
ASSERT_OK(ramdisk.status_value());
auto fvm_path = storage::CreateFvmInstance(ramdisk->path(), kFvmSliceSize);
ASSERT_OK(fvm_path.status_value());
auto fvm_client = ConnectToFvm(ramdisk->path());
ASSERT_OK(fvm_client.status_value());
auto fvm_colume = FvmVolume::Create(*fvm_client, kFvmSliceSize * 2);
ASSERT_OK(fvm_colume.status_value());
auto volume_client =
service::Connect<fuchsia_hardware_block_volume::Volume>(fvm_colume->path().c_str());
ASSERT_OK(fvm_colume.status_value());
auto info = fidl::WireCall(*volume_client)->GetVolumeInfo();
ASSERT_OK(info.status());
ASSERT_OK(info.value().status);
EXPECT_EQ(info.value().volume->partition_slice_count, 2lu);
}
TEST(BlockDeviceTest, CreateZxcryptVolumeWorks) {
auto ramdisk = storage::RamDisk::Create(kBlockSize, kBlockCount);
ASSERT_OK(ramdisk.status_value());
auto fvm_path = storage::CreateFvmInstance(ramdisk->path(), kFvmSliceSize);
ASSERT_OK(fvm_path.status_value());
auto fvm_client = ConnectToFvm(ramdisk->path());
ASSERT_OK(fvm_client.status_value());
auto fvm_volume = FvmVolume::Create(*fvm_client, kVolumeSize);
ASSERT_OK(fvm_volume.status_value());
auto zxcrypt_path = CreateZxcryptVolume(fvm_volume->path());
ASSERT_OK(zxcrypt_path.status_value());
fbl::unique_fd volume_fd(open(fvm_volume->path().c_str(), O_RDWR));
fs_management::DiskFormat format = fs_management::DetectDiskFormat(volume_fd.get());
EXPECT_EQ(format, fs_management::kDiskFormatZxcrypt);
}
TEST(BlockDeviceTest, FormatBlockDeviceWorks) {
auto ramdisk = storage::RamDisk::Create(kBlockSize, kBlockCount);
ASSERT_OK(ramdisk.status_value());
auto fvm_path = storage::CreateFvmInstance(ramdisk->path(), kFvmSliceSize);
ASSERT_OK(fvm_path.status_value());
auto fvm_client = ConnectToFvm(ramdisk->path());
ASSERT_OK(fvm_client.status_value());
auto fvm_volume = FvmVolume::Create(*fvm_client, kVolumeSize);
ASSERT_OK(fvm_volume.status_value());
auto status = FormatBlockDevice(fvm_volume->path(), fs_management::kDiskFormatMinfs);
ASSERT_OK(status.status_value());
fbl::unique_fd volume_fd(open(fvm_volume->path().c_str(), O_RDWR));
fs_management::DiskFormat format = fs_management::DetectDiskFormat(volume_fd.get());
EXPECT_EQ(format, fs_management::kDiskFormatMinfs);
}
TEST(BlockDeviceTest, FormatBlockDeviceWithZxcryptWorks) {
auto ramdisk = storage::RamDisk::Create(kBlockSize, kBlockCount);
ASSERT_OK(ramdisk.status_value());
auto fvm_path = storage::CreateFvmInstance(ramdisk->path(), kFvmSliceSize);
ASSERT_OK(fvm_path.status_value());
auto fvm_client = ConnectToFvm(ramdisk->path());
ASSERT_OK(fvm_client.status_value());
auto fvm_volume = FvmVolume::Create(*fvm_client, kVolumeSize);
ASSERT_OK(fvm_volume.status_value());
auto zxcrypt_path = CreateZxcryptVolume(fvm_volume->path());
ASSERT_OK(zxcrypt_path.status_value());
auto status = FormatBlockDevice(*zxcrypt_path, fs_management::kDiskFormatMinfs);
ASSERT_OK(status.status_value());
fbl::unique_fd minfs_fd(open(zxcrypt_path->c_str(), O_RDWR));
fs_management::DiskFormat format = fs_management::DetectDiskFormat(minfs_fd.get());
EXPECT_EQ(format, fs_management::kDiskFormatMinfs);
}
TEST(BlockDeviceTest, StartBlockDeviceFilesystemWorks) {
constexpr char kFileName[] = "file";
constexpr std::string_view kFileContents = "file-contents";
constexpr ssize_t kFileSize = kFileContents.size();
auto ramdisk = storage::RamDisk::Create(kBlockSize, kBlockCount);
ASSERT_OK(ramdisk.status_value());
auto fvm_path = storage::CreateFvmInstance(ramdisk->path(), kFvmSliceSize);
ASSERT_OK(fvm_path.status_value());
auto fvm_client = ConnectToFvm(ramdisk->path());
ASSERT_OK(fvm_client.status_value());
auto fvm_volume = FvmVolume::Create(*fvm_client, kVolumeSize);
ASSERT_OK(fvm_volume.status_value());
auto status = FormatBlockDevice(fvm_volume->path(), fs_management::kDiskFormatMinfs);
ASSERT_OK(status.status_value());
std::string block_device_path = fvm_volume->path();
auto fs = StartBlockDeviceFilesystem(block_device_path, fs_management::kDiskFormatMinfs,
*std::move(fvm_volume));
ASSERT_OK(fs.status_value());
auto root = fs->GetFilesystemRoot();
ASSERT_OK(root.status_value());
fbl::unique_fd dir;
ASSERT_OK(fdio_fd_create(root->TakeChannel().release(), dir.reset_and_get_address()));
fbl::unique_fd file(openat(dir.get(), kFileName, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR));
ASSERT_EQ(pwrite(file.get(), kFileContents.data(), kFileSize, 0), kFileSize);
std::string contents(kFileSize, 0);
ASSERT_EQ(pread(file.get(), contents.data(), kFileSize, 0), kFileSize);
EXPECT_EQ(contents, kFileContents);
}
TEST(BlockDeviceTest, StartBlockDeviceFilesystemWorksWithFxfs) {
constexpr char kFileName[] = "file";
constexpr std::string_view kFileContents = "file-contents";
constexpr ssize_t kFileSize = kFileContents.size();
constexpr uint64_t kFxfsBlockSize = 4096;
constexpr uint64_t kFxfsBlockCount = 12288;
constexpr uint64_t kFxfsVolumeSize = 8192 * kFxfsBlockSize;
auto ramdisk = storage::RamDisk::Create(kFxfsBlockSize, kFxfsBlockCount);
ASSERT_OK(ramdisk.status_value());
auto fvm_path = storage::CreateFvmInstance(ramdisk->path(), kFvmSliceSize);
ASSERT_OK(fvm_path.status_value());
auto fvm_client = ConnectToFvm(ramdisk->path());
ASSERT_OK(fvm_client.status_value());
auto fvm_volume = FvmVolume::Create(*fvm_client, kFxfsVolumeSize);
ASSERT_OK(fvm_volume.status_value());
auto status = FormatBlockDevice(fvm_volume->path(), fs_management::kDiskFormatFxfs);
ASSERT_OK(status.status_value());
std::string block_device_path = fvm_volume->path();
auto fs = StartBlockDeviceFilesystem(block_device_path, fs_management::kDiskFormatFxfs,
*std::move(fvm_volume));
ASSERT_OK(fs.status_value());
auto root = fs->GetFilesystemRoot();
ASSERT_OK(root.status_value());
fbl::unique_fd dir;
ASSERT_OK(fdio_fd_create(root->TakeChannel().release(), dir.reset_and_get_address()));
fbl::unique_fd file(openat(dir.get(), kFileName, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR));
ASSERT_EQ(pwrite(file.get(), kFileContents.data(), kFileSize, 0), kFileSize);
std::string contents(kFileSize, 0);
ASSERT_EQ(pread(file.get(), contents.data(), kFileSize, 0), kFileSize);
EXPECT_EQ(contents, kFileContents);
}
} // namespace
} // namespace storage_benchmark