blob: 99a690205b611bc3ef8670b3d479258341dbb61f [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.
#ifndef SRC_LIB_STORAGE_VFS_CPP_PAGED_VFS_H_
#define SRC_LIB_STORAGE_VFS_CPP_PAGED_VFS_H_
#include <lib/zx/pager.h>
#include <lib/zx/status.h>
#include <lib/zx/vmo.h>
#include "src/lib/storage/vfs/cpp/managed_vfs.h"
#include "src/lib/storage/vfs/cpp/pager_thread_pool.h"
namespace fs {
class PagedVnode;
// A variant of Vfs that supports paging. A PagedVfs supports PagedVnode objects.
//
// UNDER DEVELOPMENT
// =================
// Paging in the fs library is currently under active development and not ready to use yet.
// See http://fxbug.dev/51111. Long-term the paging functionality should be moved into ManagedVfs
// and all C++ filesystems should use that on Fuchsia.
class PagedVfs : public ManagedVfs {
public:
// The caller must call Init() which must succeed before using this class.
explicit PagedVfs(async_dispatcher_t* dispatcher, int num_pager_threads = 1);
~PagedVfs() override;
// Creates the pager and worker threads. If any of these fail, this class should no be used.
zx::status<> Init();
bool is_initialized() const { return pager_.is_valid(); }
// Called in response to a successful PagedVnode::VmoRead() request, this supplies paged data from
// aux_vmo to the PagedVnode's VMO to the kernel. See zx_pager_supply_pages() documentation for
// more.
zx::status<> SupplyPages(const zx::vmo& node_vmo, uint64_t offset, uint64_t length,
const zx::vmo& aux_vmo, uint64_t aux_offset);
// Called in response to a failed PagedVnode::VmoRead() request, this reports that there was an
// error populating page data. See zx_pager_op_range() documentation for more, only certain
// values are permitted for err.
zx::status<> ReportPagerError(const zx::vmo& node_vmo, uint64_t offset, uint64_t length,
zx_status_t err);
// Allocates a VMO of the given size associated with the given PagedVnode. VMOs for use with
// the pager must be allocated by this method so the page requests are routed to the correct
// PagedVnode.
//
// This function takes a reference to the vnode on behalf of the kernel paging system. This
// reference will be released when the PagedNode notices there are no references to the VMO.
//
// This function is for internal use by PagedVnode. Most callers should use
// PagedVnode::EnsureCreateVmo().
struct VmoCreateInfo {
zx::vmo vmo;
// Unique identifier for the VMO that can be used in UnregisterPagedVmo().
uint64_t id = 0;
};
zx::status<VmoCreateInfo> CreatePagedNodeVmo(fbl::RefPtr<PagedVnode> node, uint64_t size);
// Removes the PagedVnode with the given ID from the map that tracks active pager nodes. The
// ID is the one generated by CreatePagedNodeVmo().
void UnregisterPagedVmo(uint64_t paged_vmo_id) __TA_EXCLUDES(vfs_lock_);
// Callback that the PagerThreadPool uses to notify us of pager events. These calls will get
// issued on arbitrary threads.
void PagerVmoRead(uint64_t node_id, uint64_t offset, uint64_t length);
// Returns the number of VMOs registered for notifications. Used for testing.
size_t GetRegisteredPagedVmoCount() const __TA_EXCLUDES(vfs_lock_);
private:
std::unique_ptr<PagerThreadPool> pager_pool_; // Threadsafe, does not need locking.
zx::pager pager_;
// Vnodes with active references from the kernel paging system. The owning reference here
// represents the reference from the kernel to this paged VMO and should only be dropped when
// the kernel is no longer paging this node.
uint64_t next_node_id_ = 1;
std::map<uint64_t, fbl::RefPtr<PagedVnode>> paged_nodes_ __TA_GUARDED(vfs_lock_);
};
} // namespace fs
#endif // SRC_LIB_STORAGE_VFS_CPP_PAGED_VFS_H_