// 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 <fidl/fuchsia.process.lifecycle/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/wait.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 "src/lib/storage/fs_management/cpp/format.h"
#include "src/lib/storage/vfs/cpp/vfs.h"
#include "src/storage/fshost/fdio.h"
#include "src/storage/fshost/fshost-boot-args.h"
#include "src/storage/fshost/fshost_config.h"
#include "src/storage/fshost/inspect-manager.h"
#include "src/storage/memfs/memfs.h"
#include "src/storage/memfs/vnode_dir.h"

namespace fshost {

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);
  ~FsManager();

  zx_status_t Initialize(fidl::ServerEnd<fuchsia_io::Directory> dir_request,
                         fidl::ServerEnd<fuchsia_process_lifecycle::Lifecycle> lifecycle_request,
                         const fshost_config::Config& config, BlockWatcher& watcher);

  // MountPoint is a possible location that a filesystem can be installed at.
  enum class MountPoint {
    kData,
    kFactory,
    kDurable,
  };

  // Returns the fully qualified for the given mount point.
  static const char* MountPointPath(MountPoint);

  struct MountPointEndpoints {
    fidl::UnownedClientEnd<fuchsia_io::Directory> export_root;
    fidl::ServerEnd<fuchsia_io::Directory> server_end;
  };
  // Takes the server end of the specified mount point to send to a hosted filesystem. This channel
  // pair will have been collecting queued requests since fshost was started.
  //
  // This can only be called once per mount point, any calls beyond that will return std::nullopt.
  std::optional<MountPointEndpoints> TakeMountPointServerEnd(MountPoint point);

  // Registers the device path for the given mount point.
  void RegisterDevicePath(MountPoint point, std::string_view device_path);

  // Creates a connection to the /fs dir in the outgoing directory.
  zx::status<fidl::ClientEnd<fuchsia_io::Directory>> GetFsDir();

  // Asynchronously shut down all the filesystems managed by fshost and then signal the main thread
  // to exit. Calls |callback| when complete. The Shutdown process would block until
  // ReadyForShutdown is called.
  void Shutdown(fit::function<void(zx_status_t)> callback);

  FshostInspectManager& inspect_manager() { return inspect_manager_; }

  std::shared_ptr<FshostBootArgs> boot_args() { return boot_args_; }

  bool IsShutdown();
  void WaitForShutdown();
  void ReadyForShutdown();

  // 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,
                                            std::string_view 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);

  // Disables reporting.  Future calls to |FileReport| will be NOPs.
  void DisableCrashReporting() { file_crash_report_ = false; }

  // Note that additional reasons should be added sparingly, and only in cases where the data is
  // useful and it would be difficult to debug the issue otherwise.
  enum ReportReason {
    // Unable to mount due to fsck failure.
    kFsckFailure,
  };

  // Files a synthetic crash report.  This is done in the background on a new thread, so never
  // blocks. Note that there is no indication if the reporting fails.
  void FileReport(fs_management::DiskFormat format, ReportReason reason) const;

  zx_status_t AttachMount(std::string_view device_path,
                          fidl::ClientEnd<fuchsia_io::Directory> export_root,
                          std::string_view name);

  zx_status_t DetachMount(std::string_view name);

  zx::status<std::string> GetDevicePath(uint64_t fs_id);

  // Returns the filesystem root for the given mount point.
  zx::status<fidl::ClientEnd<fuchsia_io::Directory>> GetRoot(MountPoint point) const;

 private:
  class MountedFilesystem {
   public:
    struct Compare {
      using is_transparent = void;
      bool operator()(const std::unique_ptr<MountedFilesystem>& a,
                      const std::unique_ptr<MountedFilesystem>& b) const {
        return a->name_ < b->name_;
      }

      bool operator()(const std::unique_ptr<MountedFilesystem>& a, std::string_view b) const {
        return a->name_ < b;
      }

      bool operator()(std::string_view a, const std::unique_ptr<MountedFilesystem>& b) const {
        return a < b->name_;
      }
    };

    MountedFilesystem(std::string_view name, fidl::ClientEnd<fuchsia_io::Directory> export_root,
                      uint64_t fs_id)
        : name_(name), export_root_(std::move(export_root)), fs_id_(fs_id) {}
    ~MountedFilesystem();

    uint64_t fs_id() const { return fs_id_; }

   private:
    std::string name_;
    fidl::ClientEnd<fuchsia_io::Directory> export_root_;
    uint64_t fs_id_;
  };

  // Represents a channel pair for an expected filesystem instance. When fshost starts, it creates
  // these channel pairs and exposes them in its outgoing directory. They queue filesystem
  // requests, which are then serviced when the server_end is provided to the filesystem on
  // startup.
  //
  // When a filesystem to be started, the server_end is taken with TakeMountPointServerEnd and
  // replaced with std::nullopt. The server_end is then passed to the filesystem.
  struct MountNode {
    fidl::ClientEnd<fuchsia_io::Directory> export_root;
    std::optional<fidl::ServerEnd<fuchsia_io::Directory>> server_end;
  };
  std::map<MountPoint, MountNode> mount_nodes_;

  // The memfs which serves the /tmp directory.
  std::unique_ptr<memfs::Memfs> tmp_;

  std::unique_ptr<async::Loop> global_loop_;
  fs::ManagedVfs vfs_;

  // Serves inspect data.
  FshostInspectManager inspect_manager_;

  // Used to lookup configuration options stored in fuchsia.boot.Arguments
  std::shared_ptr<fshost::FshostBootArgs> boot_args_;

  fbl::RefPtr<fs::PseudoDir> svc_dir_;
  fbl::RefPtr<fs::PseudoDir> fs_dir_;
  fbl::RefPtr<fs::PseudoDir> mnt_dir_;

  // 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 shutdown_lock_;
  bool shutdown_called_ __TA_GUARDED(shutdown_lock_) = false;
  sync_completion_t shutdown_;
  sync_completion_t ready_for_shutdown_;

  bool file_crash_report_ = true;

  std::set<std::unique_ptr<MountedFilesystem>, MountedFilesystem::Compare> mounted_filesystems_;
  std::mutex device_paths_lock_;
  std::unordered_map<uint64_t, std::string> device_paths_ __TA_GUARDED(device_paths_lock_);
};

}  // namespace fshost

#endif  // SRC_STORAGE_FSHOST_FS_MANAGER_H_
