// 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/f2fs/bcache.h"

#include <fidl/fuchsia.io/cpp/wire.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>

#include <fbl/alloc_checker.h>
#include <fbl/ref_ptr.h>
#include <storage/buffer/block_buffer.h>
#include <storage/buffer/vmo_buffer.h>
#include <storage/operation/operation.h>

#include "src/storage/f2fs/f2fs_layout.h"
#include "src/storage/lib/block_client/cpp/remote_block_device.h"

namespace f2fs {

zx::result<std::unique_ptr<BcacheMapper>> CreateBcacheMapper(
    std::vector<std::unique_ptr<block_client::BlockDevice>> devices, bool* out_readonly) {
  uint64_t total_block_count = 0;
  bool readonly = false;

  std::vector<std::unique_ptr<Bcache>> bcaches;
  for (auto& device : devices) {
    fuchsia_hardware_block::wire::BlockInfo info;
    if (zx_status_t status = device->BlockGetInfo(&info); status != ZX_OK) {
      FX_LOGS(ERROR) << "Could not access device info: " << status;
      return zx::error(status);
    }

    if (info.block_size == 0 || kBlockSize % info.block_size != 0) {
      FX_LOGS(WARNING) << "f2fs block size must be multiple of underlying block size: "
                       << info.block_size;
      return zx::error(ZX_ERR_BAD_STATE);
    }

    if (info.flags & fuchsia_hardware_block::wire::Flag::kReadonly) {
      readonly = true;
    }

    uint64_t block_count = info.block_size * info.block_count / kBlockSize;
    auto bcache_or = Bcache::Create(std::move(device), block_count, kBlockSize);
    if (bcache_or.is_error()) {
      return bcache_or.take_error();
    }
    bcaches.push_back(std::move(bcache_or.value()));
    total_block_count += block_count;
  }

  // F2fs requires at least 8 segments (sb + (ckpt + sit + nat) * 2 + ssr) for its metadata, so the
  // total_block_count must be greater than 8 segments to store data.
  if (total_block_count <= kDefaultBlocksPerSegment * 8) {
    FX_LOGS(ERROR) << "block device is too small";
    return zx::error(ZX_ERR_NO_SPACE);
  }

  // The maximum volume size of f2fs is 16TiB
  if (total_block_count >= std::numeric_limits<uint32_t>::max()) {
    FX_LOGS(ERROR) << "block device is too large (> 16TiB)";
    return zx::error(ZX_ERR_OUT_OF_RANGE);
  }

  if (out_readonly) {
    *out_readonly = readonly;
  }

  return BcacheMapper::Create(std::move(bcaches));
}

zx::result<std::unique_ptr<BcacheMapper>> CreateBcacheMapper(
    std::unique_ptr<block_client::BlockDevice> device, bool* out_readonly) {
  std::vector<std::unique_ptr<block_client::BlockDevice>> devices;
  devices.push_back(std::move(device));
  return CreateBcacheMapper(std::move(devices), out_readonly);
}

zx::result<std::unique_ptr<BcacheMapper>> CreateBcacheMapper(
    fidl::ClientEnd<fuchsia_hardware_block::Block> device_channel, bool* out_readonly) {
  auto device_or = block_client::RemoteBlockDevice::Create(
      fidl::ClientEnd<fuchsia_hardware_block_volume::Volume>{device_channel.TakeChannel()});
  if (device_or.is_error()) {
    FX_LOGS(ERROR) << "could not initialize block device";
    return device_or.take_error();
  }

  bool readonly_device = false;
  auto bc_or = CreateBcacheMapper(std::move(*device_or), &readonly_device);
  if (bc_or.is_error()) {
    FX_LOGS(ERROR) << "could not create block cache";
    return bc_or.take_error();
  }
  return bc_or.take_value();
}

Bcache::Bcache(std::unique_ptr<block_client::BlockDevice> device, uint64_t max_blocks,
               block_t block_size)
    : max_blocks_(max_blocks), block_size_(block_size), device_(std::move(device)) {}

zx_status_t Bcache::BlockAttachVmo(const zx::vmo& vmo, storage::Vmoid* out) {
  return GetDevice()->BlockAttachVmo(vmo, out);
}

zx_status_t Bcache::BlockDetachVmo(storage::Vmoid vmoid) {
  return GetDevice()->BlockDetachVmo(std::move(vmoid));
}

zx::result<std::unique_ptr<Bcache>> Bcache::Create(
    std::unique_ptr<block_client::BlockDevice> device, uint64_t max_blocks, block_t block_size) {
  std::unique_ptr<Bcache> bcache(new Bcache(std::move(device), max_blocks, block_size));

  zx_status_t status = bcache->VerifyDeviceInfo();
  if (status != ZX_OK) {
    return zx::error(status);
  }

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

zx_status_t Bcache::VerifyDeviceInfo() {
  zx_status_t status = device_->BlockGetInfo(&info_);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "cannot get block device information: " << status;
    return status;
  }

  return ZX_OK;
}

zx_status_t BcacheMapper::Readblk(block_t bno, void* data) {
  if (bno >= Maxblk()) {
    return ZX_ERR_OUT_OF_RANGE;
  }

  std::lock_guard lock(buffer_mutex_);
  zx_status_t status =
      RunRequests({storage::BufferedOperation{.vmoid = buffer_.vmoid(),
                                              .op = {.type = storage::OperationType::kRead,
                                                     .vmo_offset = 0,
                                                     .dev_offset = bno,
                                                     .length = 1}}});
  if (status != ZX_OK) {
    return status;
  }
  std::memcpy(data, buffer_.Data(0), BlockSize());
  return ZX_OK;
}

zx_status_t BcacheMapper::Writeblk(block_t bno, const void* data) {
  if (bno >= Maxblk()) {
    return ZX_ERR_OUT_OF_RANGE;
  }

  std::lock_guard lock(buffer_mutex_);
  std::memcpy(buffer_.Data(0), data, BlockSize());
  return RunRequests({storage::BufferedOperation{.vmoid = buffer_.vmoid(),
                                                 .op = {.type = storage::OperationType::kWrite,
                                                        .vmo_offset = 0,
                                                        .dev_offset = bno,
                                                        .length = 1}}});
}

zx_status_t BcacheMapper::Trim(block_t start, block_t num) {
  if (!(info_.flags & fuchsia_hardware_block::wire::Flag::kTrimSupport)) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  return RunRequests({storage::BufferedOperation{.vmoid = BLOCK_VMOID_INVALID,
                                                 .op = {
                                                     .type = storage::OperationType::kTrim,
                                                     .vmo_offset = 0,
                                                     .dev_offset = start,
                                                     .length = num,
                                                 }}});
}

zx_status_t BcacheMapper::Flush() {
  for (auto& bcache : bcaches_) {
    if (auto err = bcache->Flush(); err != ZX_OK) {
      return err;
    }
  }
  return ZX_OK;
}

zx::result<std::unique_ptr<BcacheMapper>> BcacheMapper::Create(
    std::vector<std::unique_ptr<Bcache>> bcaches) {
  uint64_t total_block_count = 0;
  for (auto& bcache : bcaches) {
    ZX_ASSERT(bcache->BlockSize() == kBlockSize);
    total_block_count += bcache->Maxblk();
  }

  auto bcache = std::unique_ptr<BcacheMapper>(
      new BcacheMapper(std::move(bcaches), total_block_count, kBlockSize));

  zx_status_t status = bcache->CreateVmoBuffer();
  if (status != ZX_OK) {
    return zx::error(status);
  }
  return zx::ok(std::move(bcache));
}

zx_status_t BcacheMapper::RunRequests(const std::vector<storage::BufferedOperation>& operations) {
  std::vector<std::vector<storage::BufferedOperation>> new_operations(bcaches_.size());
  for (const auto& operation : operations) {
    if (operation.op.dev_offset + operation.op.length > Maxblk()) {
      return ZX_ERR_OUT_OF_RANGE;
    }

    uint64_t residual = operation.op.length;
    uint64_t offset = operation.op.dev_offset;

    for (size_t i = 0; i < bcaches_.size(); ++i) {
      if (offset >= bcaches_[i]->Maxblk()) {
        offset -= bcaches_[i]->Maxblk();
        continue;
      }

      uint64_t length;
      if (residual <= bcaches_[i]->Maxblk() - offset) {
        length = residual;
      } else {
        length = bcaches_[i]->Maxblk() - offset;
      }

      vmoid_t vmoid;
      if (operation.vmoid == BLOCK_VMOID_INVALID) {
        if (operation.op.type != storage::OperationType::kTrim) {
          return ZX_ERR_INVALID_ARGS;
        }
        vmoid = BLOCK_VMOID_INVALID;
      } else {
        vmoid = vmoid_tree_[operation.vmoid][i].get();
      }

      new_operations[i].push_back(storage::BufferedOperation{
          .vmoid = vmoid,
          .op = storage::Operation{
              .type = operation.op.type,
              .vmo_offset = operation.op.vmo_offset + operation.op.length - residual,
              .dev_offset = offset,
              .length = length,
              .trace_flow_id = operation.op.trace_flow_id,
          }});

      residual -= length;
      offset = 0;
      if (residual == 0) {
        break;
      }
    }
  }

  for (size_t i = 0; i < bcaches_.size(); ++i) {
    if (new_operations[i].empty()) {
      continue;
    }

    if (auto err = bcaches_[i]->RunRequests(new_operations[i]); err != ZX_OK) {
      return err;
    }
  }
  return ZX_OK;
}

zx::result<vmoid_t> BcacheMapper::FindFreeVmoId() {
  for (vmoid_t i = last_id_; i < std::numeric_limits<vmoid_t>::max(); ++i) {
    if (vmoid_tree_.find(i) == vmoid_tree_.end()) {
      last_id_ = static_cast<vmoid_t>(i + 1);
      return zx::ok(i);
    }
  }
  for (vmoid_t i = BLOCK_VMOID_INVALID + 1; i < last_id_; ++i) {
    if (vmoid_tree_.find(i) == vmoid_tree_.end()) {
      last_id_ = static_cast<vmoid_t>(i + 1);
      return zx::ok(i);
    }
  }
  return zx::error(ZX_ERR_NO_RESOURCES);
}

zx_status_t BcacheMapper::BlockAttachVmo(const zx::vmo& vmo, storage::Vmoid* out) {
  zx::result<vmoid_t> vmoid_or = FindFreeVmoId();
  if (vmoid_or.is_error()) {
    return vmoid_or.error_value();
  }

  std::vector<storage::Vmoid> new_vmoids;
  auto cleanup = fit::defer([&] {
    for (size_t i = 0; i < new_vmoids.size(); ++i) {
      bcaches_[i]->BlockDetachVmo(std::move(new_vmoids[i]));
    }
  });

  for (auto& bcache : bcaches_) {
    storage::Vmoid vmoid;
    if (auto ret = bcache->BlockAttachVmo(vmo, &vmoid); ret != ZX_OK) {
      return ret;
    }
    new_vmoids.push_back(std::move(vmoid));
  }

  vmoid_tree_.insert(std::make_pair(vmoid_or.value(), std::move(new_vmoids)));
  *out = storage::Vmoid(vmoid_or.value());
  cleanup.cancel();
  return ZX_OK;
}

zx_status_t BcacheMapper::BlockDetachVmo(storage::Vmoid vmoid) {
  auto it = vmoid_tree_.find(vmoid.get());
  if (it == vmoid_tree_.end()) {
    return ZX_ERR_NOT_FOUND;
  }

  ZX_DEBUG_ASSERT(it->second.size() == bcaches_.size());
  auto& vmoids = it->second;
  for (size_t i = 0; i < bcaches_.size(); ++i) {
    if (auto ret = bcaches_[i]->BlockDetachVmo(std::move(vmoids[i])); ret != ZX_OK) {
      return ret;
    }
  }

  vmoid_tree_.erase(it);
  [[maybe_unused]] auto leak = vmoid.TakeId();
  return ZX_OK;
}

BcacheMapper::BcacheMapper(std::vector<std::unique_ptr<Bcache>> bcaches, uint64_t max_blocks,
                           block_t block_size)
    : bcaches_(std::move(bcaches)), block_size_(block_size), max_blocks_(max_blocks) {
  uint32_t transfer_size = MAX_TRANSFER_UNBOUNDED;
  uint32_t max_block_size = 0;
  fuchsia_hardware_block::wire::Flag flag = fuchsia_hardware_block::wire::Flag::kRemovable |
                                            fuchsia_hardware_block::wire::Flag::kTrimSupport |
                                            fuchsia_hardware_block::wire::Flag::kFuaSupport;
  for (auto& bcache : bcaches_) {
    fuchsia_hardware_block::wire::BlockInfo info;
    bcache->GetDevice()->BlockGetInfo(&info);

    if (max_block_size < info.block_size) {
      max_block_size = info.block_size;
    }

    if (transfer_size > info.max_transfer_size) {
      transfer_size = info.max_transfer_size;
    }

    if (info.flags & fuchsia_hardware_block::wire::Flag::kReadonly) {
      flag |= fuchsia_hardware_block::wire::Flag::kReadonly;
    }
    if (!(info.flags & fuchsia_hardware_block::wire::Flag::kRemovable)) {
      flag &= (~fuchsia_hardware_block::wire::Flag::kRemovable);
    }
    if (!(info.flags & fuchsia_hardware_block::wire::Flag::kTrimSupport)) {
      flag &= (~fuchsia_hardware_block::wire::Flag::kTrimSupport);
    }
    if (!(info.flags & fuchsia_hardware_block::wire::Flag::kFuaSupport)) {
      flag &= (~fuchsia_hardware_block::wire::Flag::kFuaSupport);
    }
  }
  uint64_t device_block_count = max_blocks * block_size / max_block_size;

  info_ = {
      .block_count = device_block_count,
      .block_size = max_block_size,
      .max_transfer_size = transfer_size,
      .flags = flag,
  };
}

zx_status_t BcacheMapper::BlockGetInfo(fuchsia_hardware_block::wire::BlockInfo* out_info) const {
  *out_info = info_;
  return ZX_OK;
}

}  // namespace f2fs
