| // 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_STORAGE_LIB_VFS_CPP_FUCHSIA_VFS_H_ |
| #define SRC_STORAGE_LIB_VFS_CPP_FUCHSIA_VFS_H_ |
| |
| #include <fidl/fuchsia.fs/cpp/wire.h> |
| #include <fidl/fuchsia.io/cpp/wire.h> |
| #include <lib/async/dispatcher.h> |
| #include <lib/fit/function.h> |
| #include <lib/zx/channel.h> |
| #include <lib/zx/event.h> |
| #include <lib/zx/result.h> |
| #include <lib/zx/vmo.h> |
| #include <zircon/types.h> |
| |
| #include <cstdint> |
| #include <string> |
| |
| #include <fbl/intrusive_double_list.h> |
| #include <fbl/intrusive_hash_table.h> |
| #include <fbl/macros.h> |
| #include <fbl/ref_counted.h> |
| #include <fbl/ref_ptr.h> |
| |
| #include "src/storage/lib/vfs/cpp/vfs.h" |
| |
| namespace fs { |
| |
| namespace internal { |
| class Connection; |
| } // namespace internal |
| |
| // An internal version of fuchsia_io::wire::FilesystemInfo with a simpler API and default |
| // initializers. See that FIDL struct for documentation. |
| struct FilesystemInfo { |
| uint64_t total_bytes = 0; |
| uint64_t used_bytes = 0; |
| uint64_t total_nodes = 0; |
| uint64_t used_nodes = 0; |
| uint64_t free_shared_pool_bytes = 0; |
| uint64_t fs_id = 0; |
| uint32_t block_size = 0; |
| uint32_t max_filename_size = 0; |
| fuchsia_fs::VfsType fs_type = fuchsia_fs::VfsType::Unknown(); |
| std::string name; // Length must be less than MAX_FS_NAME_BUFFER. |
| |
| // To ensure global uniqueness, filesystems should create and maintain an event object. The koid |
| // of this object is guaranteed unique in the system and is used for the filesystem ID. This |
| // function extracts the koid of the given event object and sets it as the filesystem ID. |
| void SetFsId(const zx::event& event); |
| |
| // Writes this object's values to the given FIDL object. |
| fuchsia_io::wire::FilesystemInfo ToFidl() const; |
| }; |
| |
| // Vfs specialization that adds Fuchsia-specific |
| class FuchsiaVfs : public Vfs { |
| public: |
| explicit FuchsiaVfs(async_dispatcher_t* dispatcher = nullptr); |
| ~FuchsiaVfs() override; |
| |
| using ShutdownCallback = fit::callback<void(zx_status_t status)>; |
| using CloseAllConnectionsForVnodeCallback = fit::callback<void()>; |
| |
| // Unmounts the underlying filesystem. The result of shutdown is delivered via calling |closure|. |
| // |
| // |Shutdown| may be synchronous or asynchronous. The closure may be invoked before or after |
| // |Shutdown| returns. |
| virtual void Shutdown(ShutdownCallback closure) = 0; |
| |
| // Identifies if the filesystem is in the process of terminating. May be checked by active |
| // connections, which, upon reading new port packets, should ignore them and close immediately. |
| virtual bool IsTerminating() const = 0; |
| |
| // Vfs overrides. |
| zx_status_t Unlink(fbl::RefPtr<Vnode> vn, std::string_view name, bool must_be_dir) override |
| __TA_EXCLUDES(vfs_lock_); |
| |
| void TokenDiscard(zx::event ios_token) __TA_EXCLUDES(vfs_lock_); |
| zx_status_t VnodeToToken(fbl::RefPtr<Vnode> vn, zx::event* ios_token, zx::event* out) |
| __TA_EXCLUDES(vfs_lock_); |
| zx_status_t Link(zx::event token, fbl::RefPtr<Vnode> oldparent, std::string_view oldStr, |
| std::string_view newStr) __TA_EXCLUDES(vfs_lock_); |
| zx_status_t Rename(zx::event token, fbl::RefPtr<Vnode> oldparent, std::string_view oldStr, |
| std::string_view newStr) __TA_EXCLUDES(vfs_lock_); |
| |
| // Provides the implementation for fuchsia.io.Directory.QueryFilesystem(). |
| // This default implementation returns ZX_ERR_NOT_SUPPORTED. |
| virtual zx::result<FilesystemInfo> GetFilesystemInfo() __TA_EXCLUDES(vfs_lock_); |
| |
| async_dispatcher_t* dispatcher() const { return dispatcher_; } |
| void SetDispatcher(async_dispatcher_t* dispatcher); |
| |
| // Begins serving VFS messages over the specified channel. The protocol to use will be determined |
| // by the intersection of the protocols requested in |options| and those supported by |vnode|. |
| // |server_end| usually speaks a protocol that composes |fuchsia.io/Node|, but may speak an |
| // arbitrary arbitrary protocol for service connections. |
| // |
| // *NOTE*: |vnode| must be opened before calling this function, and will be automatically closed |
| // on failure. This does not apply to node reference connections, which should not open |vnode|. |
| zx_status_t Serve(const fbl::RefPtr<Vnode>& vnode, zx::channel server_end, |
| VnodeConnectionOptions options) __TA_EXCLUDES(vfs_lock_); |
| |
| // Serves a Vnode over the specified channel (used for creating new filesystems); the Vnode must |
| // be a directory. |
| zx_status_t ServeDirectory(fbl::RefPtr<Vnode> vn, |
| fidl::ServerEnd<fuchsia_io::Directory> server_end, |
| fuchsia_io::Rights rights); |
| |
| // Convenience wrapper over |ServeDirectory| with maximum rights. |
| zx_status_t ServeDirectory(fbl::RefPtr<Vnode> vn, |
| fidl::ServerEnd<fuchsia_io::Directory> server_end) { |
| return ServeDirectory(std::move(vn), std::move(server_end), fuchsia_io::Rights::kMask); |
| } |
| |
| // Closes all connections to a Vnode and calls |callback| after all connections are closed. The |
| // caller must ensure that no new connections or transactions are created during this point. |
| virtual void CloseAllConnectionsForVnode(const Vnode& node, |
| CloseAllConnectionsForVnodeCallback callback) = 0; |
| |
| bool IsTokenAssociatedWithVnode(zx::event token) __TA_EXCLUDES(vfs_lock_); |
| |
| protected: |
| // On success, |vnode| will automatically be closed when fuchsia.io/Node.Close is called, or |
| // |server_end| is closed. On failure, callers must close |vnode| if it was opened. |
| zx_status_t ServeImpl(const fbl::RefPtr<Vnode>& vnode, zx::channel server_end, |
| VnodeConnectionOptions options) __TA_EXCLUDES(vfs_lock_); |
| |
| // Starts FIDL message dispatching on |channel|, at the same time starts to manage the lifetime of |
| // |connection|. On error registering a connection, callers must close the associated vnode. |
| virtual zx_status_t RegisterConnection(std::unique_ptr<internal::Connection> connection, |
| zx::channel channel) = 0; |
| |
| private: |
| zx_status_t TokenToVnode(zx::event token, fbl::RefPtr<Vnode>* out) __TA_REQUIRES(vfs_lock_); |
| |
| fbl::HashTable<zx_koid_t, std::unique_ptr<VnodeToken>> vnode_tokens_; |
| |
| async_dispatcher_t* dispatcher_ = nullptr; |
| }; |
| |
| } // namespace fs |
| |
| #endif // SRC_STORAGE_LIB_VFS_CPP_FUCHSIA_VFS_H_ |