// Copyright 2021 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/lib/vfs/cpp/paged_vnode.h"

#include <lib/async/task.h>
#include <zircon/errors.h>

#include <memory>
#include <mutex>

#include "src/storage/lib/vfs/cpp/paged_vfs.h"

namespace fs {

PagedVnode::PagedVnode(PagedVfs& vfs) : clone_watcher_(this), vfs_(vfs) {}

void PagedVnode::VmoDirty(uint64_t offset, uint64_t length) {
  ZX_ASSERT_MSG(false, "Filesystem does not support VmoDirty() (maybe read-only filesystem).");
}

zx::result<> PagedVnode::EnsureCreatePagedVmo(uint64_t size, uint32_t options) {
  if (paged_vmo_info_.vmo.is_valid()) {
    return zx::ok();
  }
  if (!vfs_.has_value()) {
    return zx::error(ZX_ERR_BAD_STATE);  // Currently shutting down.
  }

  zx::result info_or = vfs_.value().get().CreatePagedNodeVmo(this, size, options);
  if (info_or.is_error()) {
    return info_or.take_error();
  }
  paged_vmo_info_ = std::move(info_or.value());

  return zx::ok();
}

void PagedVnode::DidClonePagedVmo() {
  // Ensure that there is an owning reference to this vnode that goes along with the VMO clones.
  // This ensures that we can continue serving page requests even if all FIDL connections are
  // closed. This reference will be released when there are no more clones.
  if (!has_clones_reference_) {
    has_clones_reference_ = fbl::RefPtr<PagedVnode>(this);

    // Watch the VMO for the presence of no children. The VMO currently has no children because we
    // just created it, but the signal will be edge-triggered.
    WatchForZeroVmoClones();
  }
}

fbl::RefPtr<Vnode> PagedVnode::FreePagedVmo() {
  if (!paged_vmo_info_.vmo.is_valid())
    return nullptr;

  // Need to stop watching before deleting the VMO or there will be no handle to stop watching.
  StopWatchingForZeroVmoClones();

  if (vfs_.has_value()) {
    vfs_.value().get().FreePagedVmo(std::move(paged_vmo_info_));
  }

  // Reset to known-state after moving (or in case the paged_vfs was destroyed and we skipped
  // moving out of it).
  paged_vmo_info_.vmo = zx::vmo();
  paged_vmo_info_.id = 0;

  // This function must not free itself since the lock must be held to call it and the caller can't
  // release a deleted lock. The has_clones_reference_ may be the last thing keeping this class
  // alive so return it to allow the caller to release it properly.
  return std::move(has_clones_reference_);
}

void PagedVnode::OnNoPagedVmoClones() {
  ZX_DEBUG_ASSERT(!has_clones());

  // It is now save to release the VMO. Since we know there are no clones, we don't have to
  // call zx_pager_detach_vmo() to stop delivery of requests. And since there are no clones, the
  // has_clones_reference_ should also be null and there shouldn't be a reference to release
  // returned by FreePagedVmo(). If there is, deleting it here would cause "this" to be deleted
  // inside its own lock which will crash.
  fbl::RefPtr<fs::Vnode> pager_reference = FreePagedVmo();
  ZX_DEBUG_ASSERT(!pager_reference);
}

void PagedVnode::OnNoPagedVmoClonesMessage(async_dispatcher_t* dispatcher, async::WaitBase* wait,
                                           zx_status_t status, const zx_packet_signal_t* signal) {
  // The system will cancel our wait on teardown if we're still watching the vmo.
  if (status == ZX_ERR_CANCELED)
    return;

  // Our clone reference must be freed, but we need to do that outside of the lock.
  fbl::RefPtr<PagedVnode> clone_reference;

  {
    std::lock_guard lock(mutex_);

    ZX_DEBUG_ASSERT(has_clones());

    if (!vfs_.has_value()) {
      return;  // Called during tear-down.
    }

    // The kernel signal delivery could have raced with us creating a new clone. Validate that there
    // are still no clones before tearing down.
    zx_info_vmo_t info;
    if (paged_vmo().get_info(ZX_INFO_VMO, &info, sizeof(info), nullptr, nullptr) != ZX_OK)
      return;  // Something wrong with the VMO, don't try to tear down.
    if (info.num_children > 0) {
      // Race with new VMO. Re-arm the clone watcher and continue as if the signal was not sent.
      WatchForZeroVmoClones();
      return;
    }

    // Move our reference for releasing outside of the lock. Clearing the member will also allow the
    // OnNoPagedVmoClones() observer to see "has_clones() == false" which is the new state.
    clone_reference = std::move(has_clones_reference_);

    StopWatchingForZeroVmoClones();
    OnNoPagedVmoClones();
  }

  // Release the reference to this class. This could be the last reference keeping it alive which
  // can cause it to be freed.
  clone_reference = nullptr;

  // THIS OBJECT IS NOW POSSIBLY DELETED.
}

void PagedVnode::WatchForZeroVmoClones() {
  clone_watcher_.set_object(paged_vmo().get());
  clone_watcher_.set_trigger(ZX_VMO_ZERO_CHILDREN);
  if (vfs_.has_value()) {
    clone_watcher_.Begin(vfs_.value().get().dispatcher());
  }
}

void PagedVnode::StopWatchingForZeroVmoClones() {
  // This needs to tolerate calls where the cancel is unnecessary.
  if (clone_watcher_.is_pending())
    clone_watcher_.Cancel();
  clone_watcher_.set_object(ZX_HANDLE_INVALID);
}

void PagedVnode::WillDestroyVfs() {
  std::lock_guard lock(mutex_);
  vfs_.reset();
}

void PagedVnode::TearDown() {
  std::lock_guard lock(mutex_);
  auto node = FreePagedVmo();
}

}  // namespace fs
