blob: 00f387a052fe2177686111b33d85fbde2f551e82 [file] [log] [blame]
// Copyright 2016 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 FS_MANAGED_VFS_H_
#define FS_MANAGED_VFS_H_
#ifndef __Fuchsia__
#error "Fuchsia-only header"
#endif
#include <lib/async/cpp/task.h>
#include <atomic>
#include <memory>
#include <fbl/intrusive_double_list.h>
#include <fbl/mutex.h>
#include <fs/internal/connection.h>
#include <fs/vfs.h>
namespace fs {
// A specialization of |Vfs| which provides a mechanism to tear down
// all active connections before it is destroyed.
//
// This class is thread-safe, but it is unsafe to shutdown the dispatch loop
// before shutting down the ManagedVfs object.
class ManagedVfs : public Vfs {
public:
ManagedVfs();
explicit ManagedVfs(async_dispatcher_t* dispatcher);
// The ManagedVfs destructor is only safe to execute if
// no connections are actively registered.
//
// To ensure that this state is achieved, it is recommended that
// clients issue a call to |Shutdown| before calling the destructor.
~ManagedVfs() override;
// Asynchronously drop all connections managed by the VFS.
//
// Invokes |handler| once when all connections are destroyed.
// It is safe to delete ManagedVfs from within the closure.
//
// It is unsafe to call Shutdown multiple times.
void Shutdown(ShutdownCallback handler) override __TA_EXCLUDES(lock_);
private:
// Posts the task for OnShutdownComplete if it is safe to do so.
void CheckForShutdownComplete() __TA_REQUIRES(lock_);
// Identifies if the filesystem has fully terminated, and is
// ready for "OnShutdownComplete" to execute.
bool IsTerminated() const __TA_REQUIRES(lock_);
// Invokes the handler from |Shutdown| once all connections have been
// released. Additionally, unmounts all sub-mounted filesystems, if any
// exist.
void OnShutdownComplete(async_dispatcher_t*, async::TaskBase*, zx_status_t status)
__TA_EXCLUDES(lock_);
void RegisterConnection(std::unique_ptr<internal::Connection> connection) final
__TA_EXCLUDES(lock_);
void UnregisterConnection(internal::Connection* connection) final __TA_EXCLUDES(lock_);
bool IsTerminating() const final;
fbl::Mutex lock_;
fbl::DoublyLinkedList<std::unique_ptr<internal::Connection>> connections_ __TA_GUARDED(lock_);
std::atomic_bool is_shutting_down_;
async::TaskMethod<ManagedVfs, &ManagedVfs::OnShutdownComplete> shutdown_task_ __TA_GUARDED(lock_){
this};
ShutdownCallback shutdown_handler_ __TA_GUARDED(lock_);
};
} // namespace fs
#endif // FS_MANAGED_VFS_H_