// Copyright 2017 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 <inttypes.h>
#include <lib/zx/status.h>

#include <memory>

#include "src/storage/minfs/allocator_reservation.h"
#include "zircon/types.h"

#ifdef __Fuchsia__
#include <lib/fzl/owned-vmo-mapper.h>
#include <lib/zx/vmo.h>

#include <fbl/auto_lock.h>
#include <fbl/mutex.h>
#include <fbl/vector.h>
#endif

#include <utility>

#include <fbl/algorithm.h>
#include <fbl/intrusive_hash_table.h>
#include <fbl/intrusive_single_list.h>
#include <fbl/macros.h>
#include <fbl/ref_ptr.h>
#include <fs/vfs.h>

#include "src/storage/minfs/minfs_private.h"
#include "src/storage/minfs/writeback.h"

namespace minfs {

zx_status_t Transaction::Create(TransactionalFs* minfs, size_t reserve_inodes,
                                size_t reserve_blocks, InodeManager* inode_manager,
                                std::unique_ptr<Transaction>* out) {
  auto transaction = std::make_unique<Transaction>(minfs, nullptr);

  if (reserve_inodes) {
    // The inode allocator is currently not accessed asynchronously.
    // However, acquiring the reservation may cause the superblock to be modified via extension,
    // so we still need to acquire the lock first.
    zx_status_t status =
        inode_manager->Reserve(transaction.get(), reserve_inodes, &transaction->inode_reservation_);
    if (status != ZX_OK) {
      return status;
    }
  }

  if (reserve_blocks) {
    zx_status_t status =
        transaction->block_reservation_->ExtendReservation(transaction.get(), reserve_blocks);
    if (status != ZX_OK) {
      *out = std::move(transaction);
      return status;
    }
  }

  *out = std::move(transaction);
  return ZX_OK;
}

std::unique_ptr<Transaction> Transaction::FromCachedBlockTransaction(
    TransactionalFs* minfs, std::unique_ptr<CachedBlockTransaction> cached_transaction) {
  auto transaction = std::make_unique<Transaction>(minfs, std::move(cached_transaction));
  return transaction;
}

Transaction::Transaction(TransactionalFs* minfs,
                         std::unique_ptr<CachedBlockTransaction> cached_transaction)
    :
#ifdef __Fuchsia__
      lock_(minfs->GetLock()),
#endif
      inode_reservation_(&minfs->GetInodeAllocator()),
      block_reservation_(cached_transaction == nullptr
                             ? std::make_unique<AllocatorReservation>(&minfs->GetBlockAllocator())
                             : cached_transaction->TakeBlockReservations()) {
}

Transaction::~Transaction() {
  // Unreserve all reserved inodes/blocks while the lock is still held.
  inode_reservation_.Cancel();
  if (block_reservation_ != nullptr) {
    block_reservation_->Cancel();
  }
}

#ifdef __Fuchsia__
void Transaction::EnqueueMetadata(storage::Operation operation, storage::BlockBuffer* buffer) {
  storage::UnbufferedOperation unbuffered_operation = {.vmo = zx::unowned_vmo(buffer->Vmo()),
                                                       .op = operation};
  metadata_operations_.Add(std::move(unbuffered_operation));
}

void Transaction::EnqueueData(storage::Operation operation, storage::BlockBuffer* buffer) {
  storage::UnbufferedOperation unbuffered_operation = {.vmo = zx::unowned_vmo(buffer->Vmo()),
                                                       .op = operation};
  data_operations_.Add(std::move(unbuffered_operation));
}

void Transaction::PinVnode(fbl::RefPtr<VnodeMinfs> vnode) {
  for (size_t i = 0; i < pinned_vnodes_.size(); i++) {
    if (pinned_vnodes_[i].get() == vnode.get()) {
      // Already pinned
      return;
    }
  }

  pinned_vnodes_.push_back(std::move(vnode));
}

std::vector<fbl::RefPtr<VnodeMinfs>> Transaction::RemovePinnedVnodes() {
  return std::move(pinned_vnodes_);
}
#else
void Transaction::EnqueueMetadata(storage::Operation operation, storage::BlockBuffer* buffer) {
  builder_.Add(operation, buffer);
}

void Transaction::EnqueueData(storage::Operation operation, storage::BlockBuffer* buffer) {
  builder_.Add(operation, buffer);
}

// No-op - don't need to pin vnodes on host.
void Transaction::PinVnode(fbl::RefPtr<VnodeMinfs> vnode) {}
#endif

zx_status_t Transaction::ExtendBlockReservation(size_t reserve_blocks) {
  return block_reservation_->ExtendReservation(this, reserve_blocks);
}

}  // namespace minfs
