// 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.

#include "src/storage/blobfs/runner.h"

#include <fidl/fuchsia.fs/cpp/wire.h>
#include <fidl/fuchsia.update.verify/cpp/wire.h>
#include <lib/inspect/service/cpp/service.h>
#include <lib/syslog/cpp/macros.h>

#include "src/lib/storage/vfs/cpp/pseudo_dir.h"
#include "src/storage/blobfs/service/admin.h"
#include "src/storage/blobfs/service/health_check.h"

namespace blobfs {

// static.
zx::status<std::unique_ptr<Runner>> Runner::Create(async::Loop* loop,
                                                   std::unique_ptr<BlockDevice> device,
                                                   const MountOptions& options,
                                                   zx::resource vmex_resource) {
  // The runner owns the blobfs, but the runner needs to be created first because it is the Vfs
  // object that Blobfs uses.
  std::unique_ptr<Runner> runner(new Runner(loop, options.paging_threads));
  if (auto status = runner->Init(); status.is_error())
    return status.take_error();

  // All of our pager threads get the deadline profile for scheduling.
  SetDeadlineProfile(runner->GetPagerThreads());

  auto blobfs_or = Blobfs::Create(loop->dispatcher(), std::move(device), runner.get(), options,
                                  std::move(vmex_resource));
  if (blobfs_or.is_error())
    return blobfs_or.take_error();

  runner->blobfs_ = std::move(blobfs_or.value());
  runner->SetReadonly(runner->blobfs_->writability() != Writability::Writable);

  return zx::ok(std::move(runner));
}

Runner::Runner(async::Loop* loop, int32_t paging_threads)
    : fs::PagedVfs(loop->dispatcher(), paging_threads), loop_(loop) {}

Runner::~Runner() {
  // Inform PagedVfs so that it can stop threads that might call out to blobfs.
  TearDown();
}

void Runner::Shutdown(fs::FuchsiaVfs::ShutdownCallback cb) {
  TRACE_DURATION("blobfs", "Runner::Unmount");
  // Shutdown all external connections to blobfs.
  ManagedVfs::Shutdown([this, cb = std::move(cb)](zx_status_t status) mutable {
    async::PostTask(dispatcher(), [this, status, cb = std::move(cb)]() mutable {
      // Manually destroy the filesystem. The promise of Shutdown is that no connections are active,
      // and destroying the Runner object should terminate all background workers.
      blobfs_ = nullptr;

      // Tell the mounting thread that the filesystem has terminated.
      loop_->Quit();

      // Tell the unmounting channel that we've completed teardown. This *must* be the last thing we
      // do because after this, the caller can assume that it's safe to destroy the runner.
      cb(status);
    });
  });
}

zx::status<fs::FilesystemInfo> Runner::GetFilesystemInfo() { return blobfs_->GetFilesystemInfo(); }

zx_status_t Runner::ServeRoot(fidl::ServerEnd<fuchsia_io::Directory> root) {
  fbl::RefPtr<fs::Vnode> vn;
  zx_status_t status = blobfs_->OpenRootNode(&vn);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "mount failed; could not get root blob";
    return status;
  }

  // Specify to fall back to DeepCopy mode instead of Live mode (the default) on failures to send
  // a Frozen copy of the tree (e.g. if we could not create a child copy of the backing VMO).
  // This helps prevent any issues with querying the inspect tree while the filesystem is under
  // load, since snapshots at the receiving end must be consistent. See fxbug.dev/57330 for details.
  inspect::TreeHandlerSettings settings{.snapshot_behavior =
                                            inspect::TreeServerSendPreference::Frozen(
                                                inspect::TreeServerSendPreference::Type::DeepCopy)};

  auto inspect_tree = fbl::MakeRefCounted<fs::Service>(
      [connector = inspect::MakeTreeHandler(blobfs_->GetMetrics()->inspector(), loop_->dispatcher(),
                                            settings)](zx::channel chan) mutable {
        connector(fidl::InterfaceRequest<fuchsia::inspect::Tree>(std::move(chan)));
        return ZX_OK;
      });

  auto outgoing = fbl::MakeRefCounted<fs::PseudoDir>(this);
  outgoing->AddEntry(kOutgoingDataRoot, std::move(vn));

  auto diagnostics_dir = fbl::MakeRefCounted<fs::PseudoDir>(this);
  outgoing->AddEntry("diagnostics", diagnostics_dir);
  diagnostics_dir->AddEntry(fuchsia::inspect::Tree::Name_, inspect_tree);

  outgoing->AddEntry(fidl::DiscoverableProtocolName<fuchsia_update_verify::BlobfsVerifier>,
                     fbl::MakeRefCounted<HealthCheckService>(loop_->dispatcher(), *blobfs_));

  outgoing->AddEntry(fidl::DiscoverableProtocolName<fuchsia_fs::Admin>,
                     fbl::MakeRefCounted<AdminService>(blobfs_->dispatcher(),
                                                       [this](fs::FuchsiaVfs::ShutdownCallback cb) {
                                                         this->Shutdown(std::move(cb));
                                                       }));

  status = ServeDirectory(std::move(outgoing), std::move(root));
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "mount failed; could not serve root directory";
    return status;
  }
  return ZX_OK;
}

bool Runner::IsReadonly() {
  std::lock_guard lock(vfs_lock_);
  return ReadonlyLocked();
}

}  // namespace blobfs
