blob: cfe190bf833f57ae308085617fe59f8163ff4280 [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.
#pragma once
#ifndef __Fuchsia__
#error "Fuchsia-only header"
#endif
#include <lib/async/cpp/task.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/function.h>
#include <fbl/unique_ptr.h>
#include <fs/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 NOT thread-safe and it must be used with a
// single-threaded asynchronous dispatcher. However, after an operation
// has been dispatched to a connection, it is safe to defer completion
// of that operation, returning "ERR_DISPATCHER_ASYNC".
//
// It is unsafe to shutdown the dispatch loop before shutting down the
// ManagedVfs object.
class ManagedVfs : public Vfs {
public:
ManagedVfs();
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.
virtual void Shutdown(ShutdownCallback handler) override;
private:
// Posts the task for OnShutdownComplete if it is safe to do so.
void CheckForShutdownComplete();
// Identifies if the filesystem has fully terminated, and is
// ready for "OnShutdownComplete" to execute.
bool IsTerminated() const;
// 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);
void RegisterConnection(fbl::unique_ptr<Connection> connection) final;
void UnregisterConnection(Connection* connection) final;
bool IsTerminating() const final;
fbl::DoublyLinkedList<fbl::unique_ptr<Connection>> connections_;
bool is_shutting_down_;
async::TaskMethod<ManagedVfs, &ManagedVfs::OnShutdownComplete> shutdown_task_{this};
ShutdownCallback shutdown_handler_;
};
} // namespace fs