blob: de941a124f106adf6e5a64309a093c56353b404d [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 <inttypes.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fbl/ref_ptr.h>
#include <fbl/unique_ptr.h>
#include <lib/fdio/namespace.h>
#include <lib/fdio/vfs.h>
#include <fs/vfs.h>
#include <lib/async/dispatcher.h>
#include <lib/memfs/cpp/vnode.h>
#include <lib/memfs/memfs.h>
#include <lib/sync/completion.h>
#include <zircon/device/vfs.h>
#include <utility>
#include "dnode.h"
struct memfs_filesystem {
memfs::Vfs vfs;
explicit memfs_filesystem(size_t pages_limit): vfs(pages_limit) { }
};
zx_status_t memfs_create_filesystem(async_dispatcher_t* dispatcher,
memfs_filesystem_t** out_fs,
zx_handle_t* out_root) {
uint64_t physmem_size = zx_system_get_physmem();
ZX_DEBUG_ASSERT(physmem_size % PAGE_SIZE == 0);
size_t page_limit = physmem_size / PAGE_SIZE;
return memfs_create_filesystem_with_page_limit(dispatcher, page_limit, out_fs, out_root);
}
zx_status_t memfs_create_filesystem_with_page_limit(async_dispatcher_t* dispatcher,
size_t max_num_pages,
memfs_filesystem_t** out_fs,
zx_handle_t* out_root) {
ZX_DEBUG_ASSERT(dispatcher != nullptr);
ZX_DEBUG_ASSERT(out_fs != nullptr);
ZX_DEBUG_ASSERT(out_root != nullptr);
zx::channel client, server;
zx_status_t status = zx::channel::create(0, &client, &server);
if (status != ZX_OK) {
return status;
}
fbl::unique_ptr<memfs_filesystem_t> fs = std::make_unique<memfs_filesystem_t>(max_num_pages);
fs->vfs.SetDispatcher(dispatcher);
fbl::RefPtr<memfs::VnodeDir> root;
if ((status = memfs::CreateFilesystem("<tmp>", &fs->vfs, &root)) != ZX_OK) {
return status;
}
if ((status = fs->vfs.ServeDirectory(std::move(root), std::move(server))) != ZX_OK) {
return status;
}
*out_fs = fs.release();
*out_root = client.release();
return ZX_OK;
}
zx_status_t memfs_install_at(async_dispatcher_t* dispatcher, const char* path) {
uint64_t physmem_size = zx_system_get_physmem();
ZX_DEBUG_ASSERT(physmem_size % PAGE_SIZE == 0);
size_t page_limit = physmem_size / PAGE_SIZE;
return memfs_install_at_with_page_limit(dispatcher, page_limit, path);
}
zx_status_t memfs_install_at_with_page_limit(async_dispatcher_t* dispatcher,
size_t max_num_pages, const char* path) {
fdio_ns_t* ns;
zx_status_t status = fdio_ns_get_installed(&ns);
if (status != ZX_OK) {
return status;
}
memfs_filesystem_t* fs;
zx_handle_t root;
status = memfs_create_filesystem_with_page_limit(dispatcher, max_num_pages, &fs, &root);
if (status != ZX_OK) {
return status;
}
status = fdio_ns_bind(ns, path, root);
if (status != ZX_OK) {
memfs_free_filesystem(fs, nullptr);
return status;
}
return ZX_OK;
}
void memfs_free_filesystem(memfs_filesystem_t* fs, sync_completion_t* unmounted) {
ZX_DEBUG_ASSERT(fs != nullptr);
fs->vfs.Shutdown([fs, unmounted](zx_status_t status) {
delete fs;
if (unmounted) {
sync_completion_signal(unmounted);
}
});
}