blob: 65cceecd850e1440b578744f9ba38a82f9c68ca2 [file] [log] [blame]
// Copyright 2019 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_FSHOST_FS_MANAGER_H_
#define SRC_STORAGE_FSHOST_FS_MANAGER_H_
#include <fuchsia/device/manager/llcpp/fidl.h>
#include <fuchsia/process/lifecycle/llcpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/wait.h>
#include <lib/memfs/cpp/vnode.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <lib/zx/channel.h>
#include <lib/zx/event.h>
#include <lib/zx/job.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
#include <array>
#include <iterator>
#include <map>
#include <fs/vfs.h>
#include "src/lib/loader_service/loader_service.h"
// Used for fshost signals.
#include "delayed-outdir.h"
#include "fdio.h"
#include "fshost-boot-args.h"
#include "inspect-manager.h"
#include "metrics.h"
#include "registry.h"
namespace devmgr {
class BlockWatcher;
// FsManager owns multiple sub-filesystems, managing them within a top-level
// in-memory filesystem.
class FsManager {
public:
explicit FsManager(std::shared_ptr<FshostBootArgs> boot_args,
std::unique_ptr<FsHostMetrics> metrics);
~FsManager();
zx_status_t Initialize(
fidl::ServerEnd<::llcpp::fuchsia::io::Directory> dir_request,
fidl::ServerEnd<::llcpp::fuchsia::process::lifecycle::Lifecycle> lifecycle_request,
fidl::ClientEnd<::llcpp::fuchsia::device::manager::Administrator> driver_admin,
std::shared_ptr<loader::LoaderServiceBase> loader, BlockWatcher& watcher);
// TODO(fxbug.dev/39588): delete this
// Starts servicing the delayed portion of the outgoing directory, called once
// "/system" has been mounted.
void FuchsiaStart() { delayed_outdir_.Start(); }
// MountPoint is a possible location that a filesystem can be installed at.
enum class MountPoint {
kUnknown = 0,
kBin,
kData,
kVolume,
kSystem,
kInstall,
kBlob,
kPkgfs,
kFactory,
kDurable,
};
// Returns the fully qualified for the given mount point.
static const char* MountPointPath(MountPoint);
constexpr static std::array<MountPoint, 9> kAllMountPoints{
MountPoint::kBin, MountPoint::kData, MountPoint::kVolume,
MountPoint::kSystem, MountPoint::kInstall, MountPoint::kBlob,
MountPoint::kPkgfs, MountPoint::kFactory, MountPoint::kDurable,
};
// Installs the filesystem with |root_directory| at |mount_point| (which must not already have an
// installed filesystem).
// |root_directory| should be a connection to a Directory, but this is not verified.
zx_status_t InstallFs(MountPoint mount_point, zx::channel root_directory);
// Stores |export_root_directory| for the filesystem installed at |mount_point|.
// This must be called before any services are forwarded (e.g. |ForwardFsService()|).
zx_status_t SetFsExportRoot(MountPoint mount_point, zx::channel export_root_directory);
// Serves connection to the root directory ("/") on |server|.
zx_status_t ServeRoot(fidl::ServerEnd<::llcpp::fuchsia::io::Directory> server);
// Serves connection to the fshost directory (exporting the "fuchsia.fshost" services) on
// |server|.
zx_status_t ServeFshostRoot(zx::channel server) { return registry_.ServeRoot(std::move(server)); }
// Asynchronously shut down all the filesystems managed by fshost and then signal the main thread
// to exit. Calls |callback| when complete.
void Shutdown(fit::function<void(zx_status_t)> callback);
// Returns a pointer to the |FsHostMetrics| instance.
FsHostMetrics* mutable_metrics() { return metrics_.get(); }
// Flushes FsHostMetrics to cobalt.
void FlushMetrics();
std::shared_ptr<FshostBootArgs> boot_args() { return boot_args_; }
bool IsShutdown();
void WaitForShutdown();
// Creates a new subdirectory in the fshost diagnostics directory by the name of
// |diagnostics_dir_name|, which forwards the diagnostics dir exposed in the export root directory
// of the given filesystem previously installed via |InstallFs()| at |point|.
zx_status_t ForwardFsDiagnosticsDirectory(MountPoint point, const char* diagnostics_dir_name);
// Creates a new subdirectory in the fshost svc directory by the name of
// |service_name|, which forwards the service by the same name exposed in the outgoing service
// directory of the given filesystem previously installed via |InstallFs()| at |point|.
zx_status_t ForwardFsService(MountPoint point, const char* service_name);
private:
zx_status_t SetupOutgoingDirectory(fidl::ServerEnd<::llcpp::fuchsia::io::Directory> dir_request,
std::shared_ptr<loader::LoaderServiceBase> loader,
BlockWatcher& watcher);
zx_status_t SetupLifecycleServer(
fidl::ServerEnd<::llcpp::fuchsia::process::lifecycle::Lifecycle> lifecycle_request);
struct MountNode {
// Set by |InstallFs()|.
zx::channel root_export_dir;
fbl::RefPtr<fs::Vnode> root_directory;
bool Installed() const { return root_export_dir.is_valid(); }
};
std::map<MountPoint, MountNode> mount_nodes_;
// Tell driver_manager to remove all drivers living in storage. This must be called before
// shutting down. `callback` will be called once all drivers living in storage have been
// unbound and removed.
void RemoveSystemDrivers(fit::callback<void(zx_status_t)> callback);
// The Root VFS manages the following filesystems:
// - The global root filesystem (including the mount points)
// - "/tmp"
std::unique_ptr<memfs::Vfs> root_vfs_;
std::unique_ptr<async::Loop> global_loop_;
fs::ManagedVfs outgoing_vfs_;
// The base, root directory which serves the rest of the fshost.
fbl::RefPtr<memfs::VnodeDir> global_root_;
// Controls the external fshost vnode, as well as registration of filesystems
// dynamically within the fshost.
fshost::Registry registry_;
// Keeps a collection of metrics being track at the FsHost level.
std::unique_ptr<FsHostMetrics> metrics_;
// Serves inspect data.
InspectManager inspect_;
// Used to lookup configuration options stored in fuchsia.boot.Arguments
std::shared_ptr<devmgr::FshostBootArgs> boot_args_;
// The outgoing service directory for fshost.
fbl::RefPtr<fs::PseudoDir> svc_dir_;
// TODO(fxbug.dev/39588): delete this
// A RemoteDir in the outgoing directory that ignores requests until Start is
// called on it.
DelayedOutdir delayed_outdir_;
// The diagnostics directory for the fshost inspect tree.
// Each filesystem gets a subdirectory to host their own inspect tree.
// Archivist will parse all the inspect trees found in this directory tree.
fbl::RefPtr<fs::PseudoDir> diagnostics_dir_;
std::mutex lock_;
bool shutdown_called_ TA_GUARDED(lock_) = false;
sync_completion_t shutdown_;
fidl::Client<llcpp::fuchsia::device::manager::Administrator> driver_admin_;
};
} // namespace devmgr
#endif // SRC_STORAGE_FSHOST_FS_MANAGER_H_