blob: dfb524d80afd58e6b02b8fd34d5c7719282c5ecb [file] [log] [blame]
// Copyright 2017 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/memfs/memfs.h"
#include <fidl/fuchsia.fs/cpp/common_types.h>
#include <lib/async/dispatcher.h>
#include <lib/zx/event.h>
#include <lib/zx/result.h>
#include <memory>
#include <string_view>
#include <fbl/ref_ptr.h>
#include <safemath/safe_math.h>
#include "src/lib/storage/vfs/cpp/fuchsia_vfs.h"
#include "src/lib/storage/vfs/cpp/paged_vfs.h"
#include "src/storage/memfs/dnode.h"
#include "src/storage/memfs/vnode_dir.h"
namespace memfs {
size_t GetPageSize() {
static const size_t kPageSize = static_cast<size_t>(zx_system_get_page_size());
return kPageSize;
}
zx::result<fs::FilesystemInfo> Memfs::GetFilesystemInfo() {
fs::FilesystemInfo info;
info.block_size = safemath::checked_cast<uint32_t>(GetPageSize());
info.max_filename_size = kDnodeNameMax;
info.fs_type = fuchsia_fs::VfsType::kMemfs;
info.SetFsId(fs_id_);
// TODO(fxbug.dev/86984) Define a better value for "unknown" or "undefined" for the total_bytes
// and used_bytes (memfs vends writable duplicates of its underlying VMOs to its clients which
// makes accounting difficult).
info.total_bytes = UINT64_MAX;
info.used_bytes = 0;
info.total_nodes = UINT64_MAX;
uint64_t deleted_ino_count = Vnode::GetDeletedInoCounter();
uint64_t ino_count = Vnode::GetInoCounter();
ZX_DEBUG_ASSERT(ino_count >= deleted_ino_count);
info.used_nodes = ino_count - deleted_ino_count;
info.name = "memfs";
return zx::ok(info);
}
zx_status_t Memfs::Create(async_dispatcher_t* dispatcher, std::string_view fs_name,
std::unique_ptr<memfs::Memfs>* out_vfs, fbl::RefPtr<VnodeDir>* out_root) {
auto fs = std::unique_ptr<memfs::Memfs>(new memfs::Memfs(dispatcher));
fbl::RefPtr<VnodeDir> root = fbl::MakeRefCounted<VnodeDir>(*fs);
std::unique_ptr<Dnode> dn = Dnode::Create(fs_name, root);
root->dnode_ = dn.get();
root->dnode_parent_ = dn->GetParent();
fs->root_ = std::move(dn);
if (zx::result<> result = fs->Init(); result.is_error()) {
return result.status_value();
}
if (zx_status_t status = zx::event::create(0, &fs->fs_id_); status != ZX_OK)
return status;
*out_root = std::move(root);
*out_vfs = std::move(fs);
return ZX_OK;
}
Memfs::Memfs(async_dispatcher_t* dispatcher) : fs::PagedVfs(dispatcher) {}
Memfs::~Memfs() { TearDown(); }
zx_status_t Memfs::CreateFromVmo(VnodeDir* parent, std::string_view name, zx_handle_t vmo,
zx_off_t off, zx_off_t len) {
std::lock_guard<std::mutex> lock(vfs_lock_);
return parent->CreateFromVmo(name, vmo, off, len);
}
} // namespace memfs