blob: d36f4787a1e195983a6331c2670ddfbdbf8af75d [file] [log] [blame]
// Copyright 2020 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 "nand_test.h"
#include <fuchsia/io/llcpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/namespace.h>
#include <lib/zx/vmar.h>
#include <blobfs/mkfs.h>
#include <block-client/cpp/remote-block-device.h>
#include "src/devices/block/bin/ftl_proxy/ftl_util.h"
namespace blobfs {
namespace {
constexpr uint32_t kPageSize = 4096;
constexpr uint32_t kOobSize = 8;
constexpr uint32_t kPagesPerBlock = 64;
constexpr uint32_t kNumBlocks = 20;
fuchsia_hardware_nand_RamNandInfo GetRamNandConfig() {
fuchsia_hardware_nand_RamNandInfo config = {};
config.nand_info.page_size = kPageSize;
config.nand_info.pages_per_block = kPagesPerBlock;
config.nand_info.num_blocks = kNumBlocks;
config.nand_info.ecc_bits = 8;
config.nand_info.oob_size = kOobSize;
config.nand_info.nand_class = fuchsia_hardware_nand_Class_FTL;
return config;
}
} // namespace
NandTest::Connection::Connection(const char* dev_root, zx::vmo vmo, bool create_filesystem) {
std::string thread_name = std::string("blobfs dispatcher for ") + std::string(dev_root);
loop_ = std::make_unique<async::Loop>(&kAsyncLoopConfigNoAttachToCurrentThread);
loop_->StartThread(thread_name.c_str());
auto ram_nand_config = GetRamNandConfig();
ASSERT_OK(ramdevice_client::RamNandCtl::Create(&ram_nand_ctl_));
fdio_ns_t* name_space = nullptr;
ASSERT_EQ(ZX_OK, fdio_ns_get_installed(&name_space));
ASSERT_EQ(ZX_OK, fdio_ns_bind_fd(name_space, dev_root, ram_nand_ctl_->devfs_root().get()));
if (vmo)
zx_handle_duplicate(vmo.get(), ZX_RIGHT_SAME_RIGHTS, &ram_nand_config.vmo);
ASSERT_EQ(ZX_OK, ramdevice_client::RamNand::Create(ram_nand_ctl_, &ram_nand_config, &ram_nand_));
// Get the FTL device path. The block device is under it.
std::string block_class = std::string(dev_root) + "/class/block";
std::string ftl = ftl_proxy::GetFtlTopologicalPath(block_class.c_str());
std::string block_device_path = ftl + "/block";
int block_fd = open(block_device_path.c_str(), O_RDWR);
ASSERT_LE(0, block_fd);
// Connect a block device client to the device.
zx::channel block_channel;
ASSERT_OK(fdio_get_service_handle(block_fd, block_channel.reset_and_get_address()));
std::unique_ptr<block_client::RemoteBlockDevice> device;
ASSERT_OK(block_client::RemoteBlockDevice::Create(std::move(block_channel), &device));
block_device_ = device.get();
if (create_filesystem) {
// Create an empty blobfs on the block device.
ASSERT_OK(blobfs::FormatFilesystem(device.get(), FilesystemOptions{}));
}
zx::channel root_client, root_server;
ASSERT_OK(zx::channel::create(0, &root_client, &root_server));
zx::channel diagnostics_dir_client, diagnostics_dir_server;
ASSERT_OK(zx::channel::create(0, &diagnostics_dir_client, &diagnostics_dir_server));
// Create the blobfs. This takes ownership of the device.
MountOptions mount_options;
mount_options.pager = true;
ASSERT_OK(blobfs::Runner::Create(loop_.get(), std::move(device), &mount_options, zx::resource(),
std::move(diagnostics_dir_server), &runner_));
ASSERT_OK(runner_->ServeRoot(std::move(root_server), blobfs::ServeLayout::kDataRootOnly));
// FDIO serving the root directory.
ASSERT_OK(fdio_fd_create(root_client.release(), root_fd_.reset_and_get_address()));
ASSERT_TRUE(root_fd_.is_valid());
}
NandTest::Connection::~Connection() {
zx::channel root_client;
ASSERT_OK(fdio_fd_transfer(root_fd_.release(), root_client.reset_and_get_address()));
ASSERT_OK(
llcpp::fuchsia::io::DirectoryAdmin::Call::Unmount(zx::unowned_channel(root_client)).status());
}
size_t NandTest::Connection::GetVMOSize() {
return (kPageSize + kOobSize) * (kPagesPerBlock * kNumBlocks);
}
void NandTest::SetUp() {}
} // namespace blobfs