blob: 8789504c7ca1c78a1a2d1f99ae3bebac5d271305 [file] [log] [blame]
// Copyright 2021 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 <lib/async-loop/cpp/loop.h>
#include <lib/fdio/namespace.h>
#include "src/storage/fs_test/fs_test.h"
#include "src/storage/lib/fs_management/cpp/mount.h"
#include "src/storage/memfs/memfs.h"
#include "src/storage/memfs/vnode_dir.h"
namespace {
class MemfsInstance : public fs_test::FilesystemInstance {
public:
MemfsInstance() : loop_(&kAsyncLoopConfigNeverAttachToThread) {}
~MemfsInstance() override { Shutdown(); }
zx::result<> Format(const fs_test::TestFilesystemOptions&) override {
Shutdown();
zx::result result = memfs::Memfs::Create(loop_.dispatcher(), "<tmp>");
if (result.is_error()) {
return result.take_error();
}
auto& [memfs, root] = result.value();
zx::result server = fidl::CreateEndpoints(&root_);
if (server.is_error()) {
return server.take_error();
}
if (zx_status_t status = memfs->ServeDirectory(std::move(root), std::move(server.value()));
status != ZX_OK) {
return zx::error(status);
}
if (zx_status_t status = loop_.StartThread(); status != ZX_OK) {
return zx::error(status);
}
memfs_ = std::move(memfs);
return zx::ok();
}
zx::result<> Mount(const std::string& mount_path,
const fs_management::MountOptions& options) override {
if (!root_) {
// Already mounted.
return zx::error(ZX_ERR_BAD_STATE);
}
fdio_ns_t* ns;
if (auto status = zx::make_result(fdio_ns_get_installed(&ns)); status.is_error()) {
return status;
}
return zx::make_result(fdio_ns_bind(ns, fs_test::StripTrailingSlash(mount_path).c_str(),
root_.TakeChannel().release()));
}
zx::result<> Unmount(const std::string& mount_path) override {
return fs_test::FsUnbind(mount_path);
}
zx::result<> Fsck() override { return zx::ok(); }
zx::result<std::string> DevicePath() const override { return zx::error(ZX_ERR_BAD_STATE); }
fs_management::SingleVolumeFilesystemInterface* fs() override { return nullptr; }
std::string GetMoniker() const override {
ZX_ASSERT_MSG(false, "GetMoniker unimplemented for MemfsInstance");
return "";
}
private:
void Shutdown() {
loop_.Quit();
loop_.JoinThreads();
zx_status_t status = loop_.ResetQuit();
ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));
}
fidl::ClientEnd<fuchsia_io::Directory> root_;
std::unique_ptr<memfs::Memfs> memfs_;
async::Loop loop_;
};
class MemfsFilesystem : public fs_test::FilesystemImpl<MemfsFilesystem> {
public:
zx::result<std::unique_ptr<fs_test::FilesystemInstance>> Make(
const fs_test::TestFilesystemOptions& options) const override {
auto instance = std::make_unique<MemfsInstance>();
zx::result<> status = instance->Format(options);
if (status.is_error()) {
return status.take_error();
}
return zx::ok(std::move(instance));
}
const Traits& GetTraits() const override {
static Traits traits{
.in_memory = true,
.is_case_sensitive = true,
.is_journaled = false,
.name = "memfs",
.supports_hard_links = true,
.supports_mmap = true,
.supports_mmap_shared_write = true,
.supports_resize = false,
.supports_sparse_files = true,
.supports_watch_event_deleted = false,
.timestamp_granularity = zx::nsec(1),
};
return traits;
}
};
} // namespace
__EXPORT std::unique_ptr<fs_test::Filesystem> GetFilesystem() {
return std::make_unique<MemfsFilesystem>();
}