// Copyright 2018 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/minfs/allocator/inode_manager.h"

#include <lib/syslog/cpp/macros.h>
#include <stdlib.h>

#include <memory>

#include <storage/buffer/block_buffer.h>

#include "src/storage/minfs/format.h"
#include "src/storage/minfs/unowned_vmo_buffer.h"

namespace minfs {

InodeManager::InodeManager(blk_t start_block, uint32_t block_size)
    : start_block_(start_block), block_size_(block_size) {}

zx::result<std::unique_ptr<InodeManager>> InodeManager::Create(
    block_client::BlockDevice* device, SuperblockManager* sb,
    fs::BufferedOperationsBuilder* builder, AllocatorMetadata metadata, blk_t start_block,
    size_t inodes) {
  auto mgr = std::unique_ptr<InodeManager>(new InodeManager(start_block, sb->BlockSize()));
  InodeManager* mgr_raw = mgr.get();

  auto grow_cb = [mgr_raw](uint32_t pool_size) { return mgr_raw->Grow(pool_size); };

  std::unique_ptr<PersistentStorage> storage(new PersistentStorage(
      device, sb, kMinfsInodeSize, std::move(grow_cb), std::move(metadata), sb->BlockSize()));
  auto inode_allocator_or = Allocator::Create(builder, std::move(storage));
  if (inode_allocator_or.is_error()) {
    return inode_allocator_or.take_error();
  }
  mgr->inode_allocator_ = std::move(inode_allocator_or.value());

  uint64_t inoblks =
      (static_cast<uint64_t>(inodes) + kMinfsInodesPerBlock - 1) / kMinfsInodesPerBlock;
  if (zx_status_t status =
          mgr->inode_table_.CreateAndMap(inoblks * sb->BlockSize(), "minfs-inode-table");
      status != ZX_OK) {
    return zx::error(status);
  }

  storage::Vmoid vmoid;
  if (zx_status_t status = device->BlockAttachVmo(mgr->inode_table_.vmo(), &vmoid);
      status != ZX_OK) {
    return zx::error(status);
  }
  vmoid_t id = vmoid.get();
  builder->AddVmoid(storage::OwnedVmoid(std::move(vmoid), device));

  storage::Operation operation{
      .type = storage::OperationType::kRead,
      .vmo_offset = 0,
      .dev_offset = start_block,
      .length = inoblks,
  };

  fs::internal::BorrowedBuffer buffer(id);
  builder->Add(operation, &buffer);

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

void InodeManager::Update(PendingWork* transaction, ino_t ino, const Inode* inode) {
  // Obtain the offset of the inode within its containing block.
  const uint32_t off_of_ino = (ino % kMinfsInodesPerBlock) * kMinfsInodeSize;
  const blk_t inoblock_rel = ino / kMinfsInodesPerBlock;
  const blk_t inoblock_abs = inoblock_rel + start_block_;
  ZX_DEBUG_ASSERT(inoblock_abs < kFVMBlockDataStart);

  char* inodata = reinterpret_cast<char*>(inode_table_.start()) +
                  inoblock_rel * static_cast<size_t>(BlockSize());
  memcpy(inodata + off_of_ino, inode, kMinfsInodeSize);

  storage::Operation operation = {
      .type = storage::OperationType::kWrite,
      .vmo_offset = inoblock_rel,
      .dev_offset = inoblock_abs,
      .length = 1,
  };
  UnownedVmoBuffer buffer(zx::unowned_vmo(inode_table_.vmo()));
  transaction->EnqueueMetadata(operation, &buffer);
}

const Allocator* InodeManager::GetInodeAllocator() const { return inode_allocator_.get(); }

void InodeManager::Load(ino_t ino, Inode* out) const {
  // Obtain the block of the inode table we need.
  uint32_t off_of_ino = (ino % kMinfsInodesPerBlock) * kMinfsInodeSize;
  const char* inodata = reinterpret_cast<const char*>(inode_table_.start()) +
                        ino / kMinfsInodesPerBlock * static_cast<size_t>(BlockSize());
  const Inode* inode = reinterpret_cast<const Inode*>(inodata + off_of_ino);
  memcpy(out, inode, kMinfsInodeSize);
}

zx_status_t InodeManager::Grow(size_t inodes) {
  size_t inoblks = (inodes + kMinfsInodesPerBlock - 1) / kMinfsInodesPerBlock;
  if (zx_status_t status = inode_table_.Grow(inoblks * BlockSize()); status != ZX_OK) {
    FX_LOGS(WARNING) << "InodeManager::Grow: failed: " << status;
    return ZX_ERR_NO_SPACE;
  }
  return ZX_OK;
}

}  // namespace minfs
