// 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 "src/storage/fs_test/fs_test.h"

#include <errno.h>
#include <fuchsia/device/llcpp/fidl.h>
#include <fuchsia/fs/cpp/fidl.h>
#include <fuchsia/hardware/nand/c/fidl.h>
#include <fuchsia/io/llcpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/directory.h>
#include <lib/fzl/vmo-mapper.h>
#include <lib/memfs/memfs.h>
#include <lib/sync/completion.h>
#include <lib/zx/channel.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zircon/errors.h>

#include <iostream>
#include <utility>

#include <fbl/unique_fd.h>
#include <fs-management/admin.h>
#include <fs-management/format.h>
#include <fs-management/launch.h>
#include <fs-management/mount.h>

#include "src/lib/isolated_devmgr/v2_component/bind_devfs_to_namespace.h"
#include "src/lib/isolated_devmgr/v2_component/fvm.h"
#include "src/storage/fs_test/blobfs_test.h"
#include "src/storage/fs_test/minfs_test.h"

namespace fs_test {

namespace fio = ::llcpp::fuchsia::io;

// Creates a ram-disk with an optional FVM partition. Returns the ram-disk and the device path.
static zx::status<std::pair<isolated_devmgr::RamDisk, std::string>> CreateRamDisk(
    const TestFilesystemOptions& options) {
  zx::vmo vmo;
  fzl::VmoMapper mapper;
  auto status =
      zx::make_status(mapper.CreateAndMap(options.device_block_size * options.device_block_count,
                                          ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, nullptr, &vmo));
  if (status.is_error()) {
    std::cerr << "Unable to create VMO for ramdisk: " << status.status_string();
    return status.take_error();
  }

  // Fill the ram-disk with a non-zero value so that we don't inadvertently depend on it being
  // zero filled.
  if (!options.zero_fill) {
    memset(mapper.start(), 0xaf, mapper.size());
  }

  // Create a ram-disk.
  auto ram_disk_or =
      isolated_devmgr::RamDisk::CreateWithVmo(std::move(vmo), options.device_block_size);
  if (ram_disk_or.is_error()) {
    return ram_disk_or.take_error();
  }

  // Create an FVM partition if requested.
  std::string device_path;
  if (options.use_fvm) {
    auto fvm_partition_or =
        isolated_devmgr::CreateFvmPartition(ram_disk_or.value().path(), options.fvm_slice_size);
    if (fvm_partition_or.is_error()) {
      return fvm_partition_or.take_error();
    }
    device_path = fvm_partition_or.value();
  } else {
    device_path = ram_disk_or.value().path();
  }

  return zx::ok(std::make_pair(std::move(ram_disk_or).value(), device_path));
}

// Creates a ram-nand device.  It does not create an FVM partition; that is left to the caller.
static zx::status<std::pair<ramdevice_client::RamNand, std::string>> CreateRamNand(
    const TestFilesystemOptions& options) {
  auto status = isolated_devmgr::OneTimeSetUp();
  if (status.is_error()) {
    return status.take_error();
  }

  constexpr int kPageSize = 4096;
  constexpr int kPagesPerBlock = 64;
  constexpr int kOobSize = 8;

  uint32_t block_count;
  zx::vmo vmo;
  if (options.ram_nand_vmo->is_valid()) {
    uint64_t vmo_size;
    status = zx::make_status(options.ram_nand_vmo->get_size(&vmo_size));
    if (status.is_error()) {
      return status.take_error();
    }
    block_count = vmo_size / (kPageSize + kOobSize) / kPagesPerBlock;
    // For now, when using a ram-nand device, the only supported device block size is 8 KiB, so
    // raise an error if the user tries to ask for something different.
    if ((options.device_block_size != 0 && options.device_block_size != 8192) ||
        (options.device_block_count != 0 &&
         options.device_block_size * options.device_block_count !=
             block_count * kPageSize * kPagesPerBlock)) {
      return zx::error(ZX_ERR_INVALID_ARGS);
    }
    status =
        zx::make_status(options.ram_nand_vmo->create_child(ZX_VMO_CHILD_SLICE, 0, vmo_size, &vmo));
    if (status.is_error()) {
      return status.take_error();
    }
  } else if (options.device_block_size != 8192) {  // FTL exports a device with 8 KiB blocks.
    return zx::error(ZX_ERR_INVALID_ARGS);
  } else {
    block_count =
        options.device_block_size * options.device_block_count / kPageSize / kPagesPerBlock;
  }

  status = zx::make_status(wait_for_device("/dev/misc/nand-ctl", zx::sec(10).get()));
  if (status.is_error()) {
    std::cerr << "Timed out waiting for /dev/misc/nand-ctl to appear";
    return status.take_error();
  }

  std::optional<ramdevice_client::RamNand> ram_nand;
  fuchsia_hardware_nand_RamNandInfo config = {
      .vmo = vmo.release(),
      .nand_info.page_size = kPageSize,
      .nand_info.pages_per_block = kPagesPerBlock,
      .nand_info.num_blocks = block_count,
      .nand_info.ecc_bits = 8,
      .nand_info.oob_size = kOobSize,
      .nand_info.nand_class = fuchsia_hardware_nand_Class_FTL};
  status = zx::make_status(ramdevice_client::RamNand::Create(&config, &ram_nand));
  if (status.is_error()) {
    std::cerr << "RamNand::Create failed: " << status.status_string();
    return status.take_error();
  }

  std::string ftl_path = std::string(ram_nand->path()) + "/ftl/block";
  status = zx::make_status(wait_for_device(ftl_path.c_str(), zx::sec(10).get()));
  if (status.is_error()) {
    std::cerr << "Timed out waiting for RamNand";
    return status.take_error();
  }
  return zx::ok(std::make_pair(*std::move(ram_nand), std::move(ftl_path)));
}

// A wrapper around fs-management that can be used by filesytems if they so wish.
static zx::status<> FsMount(const std::string& device_path, const std::string& mount_path,
                            disk_format_t format, const mount_options_t& mount_options,
                            zx::channel* outgoing_directory = nullptr) {
  auto fd = fbl::unique_fd(open(device_path.c_str(), O_RDWR));
  if (!fd) {
    std::cerr << "Could not open device: " << device_path << ": errno=" << errno;
    return zx::error(ZX_ERR_BAD_STATE);
  }

  mount_options_t options = mount_options;
  options.register_fs = false;
  if (outgoing_directory) {
    zx::channel server;
    auto status = zx::make_status(zx::channel::create(0, outgoing_directory, &server));
    if (status.is_error()) {
      std::cerr << "Unable to create channel for outgoing directory: " << status.status_string();
      return status;
    }
    options.outgoing_directory.client = outgoing_directory->get();
    options.outgoing_directory.server = server.release();
  }

  // Uncomment the following line to force an fsck at the end of every transaction (where
  // supported).
  // options.fsck_after_every_transaction = true;

  // |fd| is consumed by mount.
  auto status = zx::make_status(
      mount(fd.release(), mount_path.c_str(), format, &options, launch_stdio_async));
  if (status.is_error()) {
    std::cerr << "Could not mount " << disk_format_string(format)
              << " file system: " << status.status_string();
    return status;
  }
  return zx::ok();
}

TestFilesystemOptions TestFilesystemOptions::DefaultMinfs() {
  return TestFilesystemOptions{.description = "MinfsWithFvm",
                               .use_fvm = true,
                               .device_block_size = 512,
                               .device_block_count = 131'072,
                               .fvm_slice_size = 32'768,
                               .filesystem = &MinfsFilesystem::SharedInstance()};
}

TestFilesystemOptions TestFilesystemOptions::MinfsWithoutFvm() {
  TestFilesystemOptions minfs_with_no_fvm = TestFilesystemOptions::DefaultMinfs();
  minfs_with_no_fvm.description = "MinfsWithoutFvm";
  minfs_with_no_fvm.use_fvm = false;
  return minfs_with_no_fvm;
}

TestFilesystemOptions TestFilesystemOptions::DefaultMemfs() {
  return TestFilesystemOptions{.description = "Memfs",
                               .filesystem = &MemfsFilesystem::SharedInstance()};
}

TestFilesystemOptions TestFilesystemOptions::DefaultFatfs() {
  return TestFilesystemOptions{.description = "Fatfs",
                               .use_fvm = false,
                               .device_block_size = 512,
                               .device_block_count = 196'608,
                               .filesystem = &FatFilesystem::SharedInstance()};
}

TestFilesystemOptions TestFilesystemOptions::DefaultBlobfs() {
  return TestFilesystemOptions{.description = "Blobfs",
                               .use_fvm = true,
                               .device_block_size = 512,
                               .device_block_count = 196'608,
                               .fvm_slice_size = 32'768,
                               .filesystem = &BlobfsFilesystem::SharedInstance()};
}

TestFilesystemOptions TestFilesystemOptions::BlobfsWithoutFvm() {
  TestFilesystemOptions blobfs_with_no_fvm = TestFilesystemOptions::DefaultBlobfs();
  blobfs_with_no_fvm.description = "BlobfsWithoutFvm";
  blobfs_with_no_fvm.use_fvm = false;
  return blobfs_with_no_fvm;
}

std::ostream& operator<<(std::ostream& out, const TestFilesystemOptions& options) {
  return out << options.description;
}

std::vector<TestFilesystemOptions> AllTestMinfs() {
  return std::vector<TestFilesystemOptions>{TestFilesystemOptions::DefaultMinfs(),
                                            TestFilesystemOptions::MinfsWithoutFvm()};
}

// Note: blobfs is intentionally absent, since it is not intended to run as part of the
// fs_test suite.
std::vector<TestFilesystemOptions> AllTestFilesystems() {
  return std::vector<TestFilesystemOptions>{
      TestFilesystemOptions::DefaultMinfs(), TestFilesystemOptions::MinfsWithoutFvm(),
      TestFilesystemOptions::DefaultMemfs(), TestFilesystemOptions::DefaultFatfs()};
}

std::vector<TestFilesystemOptions> MapAndFilterAllTestFilesystems(
    std::function<std::optional<TestFilesystemOptions>(const TestFilesystemOptions&)>
        map_and_filter) {
  std::vector<TestFilesystemOptions> results;
  for (const TestFilesystemOptions& options : AllTestFilesystems()) {
    auto r = map_and_filter(options);
    if (r) {
      results.push_back(*std::move(r));
    }
  }
  return results;
}

zx::status<> Filesystem::Format(const std::string& device_path, disk_format_t format) {
  mkfs_options_t options = default_mkfs_options;
  options.sectors_per_cluster = 2;  // 1 KiB cluster size
  auto status = zx::make_status(mkfs(device_path.c_str(), format, launch_stdio_sync, &options));
  if (status.is_error()) {
    std::cerr << "Could not format " << disk_format_string(format)
              << " file system: " << status.status_string();
    return status;
  }
  return zx::ok();
}

// -- Minfs --

class MinfsInstance : public FilesystemInstance {
 public:
  using Device = std::variant<isolated_devmgr::RamDisk, ramdevice_client::RamNand>;

  MinfsInstance(Device device, std::string device_path)
      : device_(std::move(device)), device_path_(std::move(device_path)) {}

  zx::status<> Mount(const std::string& mount_path) override {
    return FsMount(device_path_, mount_path, DISK_FORMAT_MINFS, default_mount_options);
  }

  zx::status<> Unmount(const std::string& mount_path) override {
    return zx::make_status(umount(mount_path.c_str()));
  }

  zx::status<> Fsck() override {
    fsck_options_t options{
        .verbose = false,
        .never_modify = true,
        .always_modify = false,
        .force = true,
        .apply_journal = false,
    };
    return zx::make_status(
        fsck(device_path_.c_str(), DISK_FORMAT_MINFS, &options, launch_stdio_sync));
  }

  zx::status<std::string> DevicePath() const override { return zx::ok(std::string(device_path_)); }

  isolated_devmgr::RamDisk* GetRamDisk() override {
    return std::get_if<isolated_devmgr::RamDisk>(&device_);
  }

  ramdevice_client::RamNand* GetRamNand() override {
    return std::get_if<ramdevice_client::RamNand>(&device_);
  }

 private:
  Device device_;
  std::string device_path_;
};

zx::status<std::unique_ptr<FilesystemInstance>> MinfsFilesystem::Make(
    const TestFilesystemOptions& options) const {
  std::optional<MinfsInstance::Device> device;
  std::string device_path;
  if (options.use_ram_nand) {
    auto ram_nand_or = CreateRamNand(options);
    if (ram_nand_or.is_error()) {
      return ram_nand_or.take_error();
    }
    auto [ram_nand, nand_device_path] = std::move(ram_nand_or).value();

    auto fvm_partition_or =
        isolated_devmgr::CreateFvmPartition(nand_device_path, options.fvm_slice_size);
    if (fvm_partition_or.is_error()) {
      std::cerr << "Failed to create FVM partition: " << fvm_partition_or.status_string();
      return fvm_partition_or.take_error();
    }

    device = std::move(ram_nand);
    device_path = fvm_partition_or.value();
  } else {
    auto ram_disk_or = CreateRamDisk(options);
    if (ram_disk_or.is_error()) {
      return ram_disk_or.take_error();
    }
    std::tie(device, device_path) = std::move(ram_disk_or).value();
  }
  zx::status<> status = Filesystem::Format(device_path, DISK_FORMAT_MINFS);
  if (status.is_error()) {
    return status.take_error();
  }
  return zx::ok(std::make_unique<MinfsInstance>(*std::move(device), device_path));
}

zx::status<std::unique_ptr<FilesystemInstance>> MinfsFilesystem::Open(
    const TestFilesystemOptions& options) const {
  if (!options.use_ram_nand || !options.ram_nand_vmo->is_valid()) {
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }

  // First create the ram-nand device.
  auto ram_nand_or = CreateRamNand(options);
  if (ram_nand_or.is_error()) {
    return ram_nand_or.take_error();
  }
  auto [ram_nand, ftl_device_path] = std::move(ram_nand_or).value();

  // Now bind FVM to it.
  zx::channel local, remote;
  auto status = zx::make_status(zx::channel::create(0, &local, &remote));
  if (status.is_error()) {
    return status.take_error();
  }

  status = zx::make_status(fdio_service_connect(ftl_device_path.c_str(), remote.release()));
  if (status.is_error()) {
    return status.take_error();
  }

  fidl::StringView fvm_driver = fidl::StringView("/pkg/bin/driver/fvm.so");
  auto resp = llcpp::fuchsia::device::Controller::Call::Bind(zx::unowned_channel(local),
                                                             std::move(fvm_driver));
  status = zx::make_status(resp.status());
  if (status.is_ok()) {
    if (resp->result.is_err()) {
      status = zx::make_status(resp->result.err());
    }
  }
  if (status.is_error()) {
    std::cerr << "Unable to bind FVM: " << status.status_string();
    return status.take_error();
  }

  // Wait for the Minfs partition to show up.
  const std::string device_path = ftl_device_path + "/fvm/fs-test-partition-p-1/block";
  status = zx::make_status(wait_for_device(device_path.c_str(), zx::sec(10).get()));
  if (status.is_error()) {
    std::cerr << "Timed out waiting for Minfs partition to show up";
    return status.take_error();
  }
  return zx::ok(std::make_unique<MinfsInstance>(std::move(ram_nand), device_path));
}

// -- Memfs --

class MemfsInstance : public FilesystemInstance {
 public:
  MemfsInstance() : loop_(&kAsyncLoopConfigNeverAttachToThread) {
    ZX_ASSERT(loop_.StartThread() == ZX_OK);
  }
  ~MemfsInstance() override {
    if (fs_) {
      sync_completion_t sync;
      memfs_free_filesystem(fs_, &sync);
      ZX_ASSERT(sync_completion_wait(&sync, zx::duration::infinite().get()) == ZX_OK);
    }
  }
  zx::status<> Format() {
    return zx::make_status(
        memfs_create_filesystem(loop_.dispatcher(), &fs_, root_.reset_and_get_address()));
  }

  zx::status<> Mount(const std::string& mount_path) override {
    if (!root_) {
      // Already mounted.
      return zx::error(ZX_ERR_BAD_STATE);
    }
    auto status = zx::make_status(mount_root_handle(root_.release(), mount_path.c_str()));
    if (status.is_error())
      std::cerr << "Unable to mount: " << status.status_string();
    return status;
  }

  zx::status<> Unmount(const std::string& mount_path) override {
    // We can't use fs-management here because it also shuts down the file system, which we don't
    // want to do because then we wouldn't be able to remount. O_ADMIN and O_NOREMOTE are not
    // available in the SDK, which makes detaching the remote mount ourselves difficult.  So, for
    // now, just do nothing; we don't really need to test this.
    return zx::ok();
  }

  zx::status<> Fsck() override { return zx::ok(); }

  zx::status<std::string> DevicePath() const override { return zx::error(ZX_ERR_BAD_STATE); }

 private:
  async::Loop loop_;
  memfs_filesystem_t* fs_ = nullptr;
  zx::channel root_;  // Not valid after mounted.
};

zx::status<std::unique_ptr<FilesystemInstance>> MemfsFilesystem::Make(
    const TestFilesystemOptions& options) const {
  auto instance = std::make_unique<MemfsInstance>();
  zx::status<> status = instance->Format();
  if (status.is_error()) {
    return status.take_error();
  }
  return zx::ok(std::move(instance));
}

// -- Fatfs --

class FatfsInstance : public FilesystemInstance {
 public:
  FatfsInstance(isolated_devmgr::RamDisk ram_disk, std::string device_path)
      : ram_disk_(std::move(ram_disk)), device_path_(std::move(device_path)) {}

  zx::status<> Mount(const std::string& mount_path) override {
    mount_options_t options = default_mount_options;
    // Fatfs doesn't support DirectoryAdmin.
    options.admin = false;
    return FsMount(device_path_, mount_path, DISK_FORMAT_FAT, options, &outgoing_directory_);
  }

  zx::status<> Unmount(const std::string& mount_path) override {
    // O_ADMIN & O_NO_REMOTE are not part of the SDK and O_ADMIN, at least, is deprecated, so for
    // now, we hard code their values until we get around to fixing fs-management. fatfs doesn't
    // support O_ADMIN.

    // First detach the node.
    constexpr int kAdmin = 0x0000'0004;
    constexpr int kNoRemote = 0x0020'0000;
    auto fd = fbl::unique_fd(open(mount_path.c_str(), O_DIRECTORY | kNoRemote | kAdmin));
    if (!fd) {
      std::cerr << "Unable to open mount point for unmount: " << strerror(errno);
      return zx::error(ZX_ERR_IO);
    }
    fdio_cpp::FdioCaller caller(std::move(fd));
    auto response = fio::DirectoryAdmin::Call::UnmountNode(caller.channel());
    caller.release().release();
    if (!response.ok()) {
      auto status = zx::make_status(response.status());
      std::cerr << "UnmountNode failed with fidl error: " << status.status_string();
      return status;
    }
    if (response.value().s != ZX_OK) {
      auto status = zx::make_status(response.value().s);
      std::cerr << "UnmountNode failed: " << status.status_string();
      return status;
    }

    // Now shut down the filesystem.
    fidl::SynchronousInterfacePtr<fuchsia::fs::Admin> admin;
    std::string service_name = std::string("svc/") + fuchsia::fs::Admin::Name_;
    auto status = zx::make_status(fdio_service_connect_at(
        outgoing_directory_.get(), service_name.c_str(), admin.NewRequest().TakeChannel().get()));
    if (status.is_error()) {
      std::cerr << "Unable to connect to admin service: " << status.status_string();
      return status;
    }
    status = zx::make_status(admin->Shutdown());
    if (status.is_error()) {
      std::cerr << "Shut down failed: " << status.status_string();
      return status;
    }
    outgoing_directory_.reset();

    return zx::ok();
  }

  zx::status<> Fsck() override {
    fsck_options_t options{
        .verbose = false,
        .never_modify = true,
        .always_modify = false,
        .force = true,
        .apply_journal = false,
    };
    return zx::make_status(
        fsck(device_path_.c_str(), DISK_FORMAT_FAT, &options, launch_stdio_sync));
  }

  zx::status<std::string> DevicePath() const override { return zx::ok(std::string(device_path_)); }

 private:
  isolated_devmgr::RamDisk ram_disk_;
  std::string device_path_;
  zx::channel outgoing_directory_;
};

zx::status<std::unique_ptr<FilesystemInstance>> FatFilesystem::Make(
    const TestFilesystemOptions& options) const {
  auto ram_disk_or = CreateRamDisk(options);
  if (ram_disk_or.is_error()) {
    return ram_disk_or.take_error();
  }
  auto [ram_disk, device_path] = std::move(ram_disk_or).value();
  zx::status<> status = Filesystem::Format(device_path, DISK_FORMAT_FAT);
  if (status.is_error()) {
    return status.take_error();
  }
  return zx::ok(std::make_unique<FatfsInstance>(std::move(ram_disk), device_path));
}

// -- Blobfs --

class BlobfsInstance : public FilesystemInstance {
 public:
  BlobfsInstance(isolated_devmgr::RamDisk ram_disk, std::string device_path)
      : ram_disk_(std::move(ram_disk)), device_path_(std::move(device_path)) {}

  zx::status<> Mount(const std::string& mount_path) override {
    return FsMount(device_path_, mount_path, DISK_FORMAT_BLOBFS, default_mount_options);
  }

  zx::status<> Unmount(const std::string& mount_path) override {
    return zx::make_status(umount(mount_path.c_str()));
  }

  zx::status<> Fsck() override {
    fsck_options_t options{
        .verbose = false,
        .never_modify = true,
        .always_modify = false,
        .force = true,
        .apply_journal = false,
    };
    return zx::make_status(
        fsck(device_path_.c_str(), DISK_FORMAT_BLOBFS, &options, launch_stdio_sync));
  }

  zx::status<std::string> DevicePath() const override { return zx::ok(std::string(device_path_)); }
  isolated_devmgr::RamDisk* GetRamDisk() override { return &ram_disk_; }

 private:
  isolated_devmgr::RamDisk ram_disk_;
  std::string device_path_;
};

zx::status<std::unique_ptr<FilesystemInstance>> BlobfsFilesystem::Make(
    const TestFilesystemOptions& options) const {
  auto ram_disk_or = CreateRamDisk(options);
  if (ram_disk_or.is_error()) {
    return ram_disk_or.take_error();
  }
  auto [ram_disk, device_path] = std::move(ram_disk_or).value();
  zx::status<> status = Filesystem::Format(device_path, DISK_FORMAT_BLOBFS);
  if (status.is_error()) {
    return status.take_error();
  }
  return zx::ok(std::make_unique<BlobfsInstance>(std::move(ram_disk), device_path));
}

// --

zx::status<TestFilesystem> TestFilesystem::FromInstance(
    const TestFilesystemOptions& options, std::unique_ptr<FilesystemInstance> instance) {
  // Mount the file system.
  char mount_path_c_str[] = "/tmp/fs_test.XXXXXX";
  if (mkdtemp(mount_path_c_str) == nullptr) {
    std::cerr << "Unable to create mount point: " << errno;
    return zx::error(ZX_ERR_BAD_STATE);
  }
  TestFilesystem filesystem(options, std::move(instance), std::string(mount_path_c_str) + "/");
  auto status = filesystem.Mount();
  if (status.is_error()) {
    return status.take_error();
  }
  return zx::ok(std::move(filesystem));
}

zx::status<TestFilesystem> TestFilesystem::Create(const TestFilesystemOptions& options) {
  auto instance_or = options.filesystem->Make(options);
  if (instance_or.is_error()) {
    return instance_or.take_error();
  }
  return FromInstance(options, std::move(instance_or).value());
}

zx::status<TestFilesystem> TestFilesystem::Open(const TestFilesystemOptions& options) {
  auto instance_or = options.filesystem->Open(options);
  if (instance_or.is_error()) {
    return instance_or.take_error();
  }
  return FromInstance(options, std::move(instance_or).value());
}

TestFilesystem::~TestFilesystem() {
  if (filesystem_) {
    if (mounted_) {
      auto status = Unmount();
      if (status.is_error()) {
        std::cerr << "warning: failed to unmount: " << status.status_string();
      }
    }
    rmdir(mount_path_.c_str());
  }
}

zx::status<> TestFilesystem::Mount() {
  auto status = filesystem_->Mount(mount_path_);
  if (status.is_ok()) {
    mounted_ = true;
  }
  return status;
}

zx::status<> TestFilesystem::Unmount() {
  if (!filesystem_) {
    return zx::ok();
  }
  auto status = filesystem_->Unmount(mount_path_);
  if (status.is_ok()) {
    mounted_ = false;
  }
  return status;
}

zx::status<> TestFilesystem::Fsck() { return filesystem_->Fsck(); }

zx::status<std::string> TestFilesystem::DevicePath() const { return filesystem_->DevicePath(); }

}  // namespace fs_test
