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

#include <assert.h>
#include <fuchsia/device/c/fidl.h>
#include <fuchsia/io/llcpp/fidl.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <utility>

#include <block-client/cpp/remote-block-device.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>


namespace f2fs {

std::unique_ptr<block_client::BlockDevice> Bcache::Destroy(std::unique_ptr<Bcache> bcache) {
  {
    // Destroy the VmoBuffer before extracting the underlying device, as it needs
    // to de-register itself from the underlying block device to be terminated.
    __UNUSED auto unused = std::move(bcache->buffer_);
  }
  return std::move(bcache->owned_device_);
}

zx_status_t Bcache::Readblk(block_t bno, void* data) {
  TRACE_DURATION("f2fs", "Bcache::Readblk", "blk", bno);
  storage::Operation operation = {};
  operation.type = storage::OperationType::kRead;
  operation.vmo_offset = 0;
  operation.dev_offset = bno;
  operation.length = 1;
  zx_status_t status = RunOperation(operation, &buffer_);
  if (status != ZX_OK) {
    return status;
  }
  memcpy(data, buffer_.Data(0), BlockSize());
  return ZX_OK;
}

zx_status_t Bcache::Writeblk(block_t bno, const void* data) {
  TRACE_DURATION("f2fs", "Bcache::Writeblk", "blk", bno);
  storage::Operation operation = {};
  operation.type = storage::OperationType::kWrite;
  operation.vmo_offset = 0;
  operation.dev_offset = bno;
  operation.length = 1;
  memcpy(buffer_.Data(0), data, BlockSize());
  return RunOperation(operation, &buffer_);
}

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

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

zx_status_t Bcache::Sync() {
  block_fifo_request_t request = {};
  request.opcode = BLOCKIO_FLUSH;
  return device_->FifoTransaction(&request, 1);
}

zx_status_t FdToBlockDevice(fbl::unique_fd& fd, std::unique_ptr<block_client::BlockDevice>* out) {
  zx::channel channel, server;
  zx_status_t status = zx::channel::create(0, &channel, &server);
  if (status != ZX_OK) {
    return status;
  }
  fdio_cpp::UnownedFdioCaller caller(fd.get());
  status =
      ::fuchsia_io::Node::Call::Clone(zx::unowned_channel(caller.borrow_channel()),
                                      ::fuchsia_io::wire::CLONE_FLAG_SAME_RIGHTS, std::move(server))
          .status();
  if (status != ZX_OK) {
    return status;
  }
  std::unique_ptr<block_client::RemoteBlockDevice> device;
  status = block_client::RemoteBlockDevice::Create(std::move(channel), &device);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "cannot create block device: " << status;
    return status;
  }

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

zx_status_t Bcache::Create(std::unique_ptr<block_client::BlockDevice> device, uint32_t max_blocks,
                           std::unique_ptr<Bcache>* out) {
  zx_status_t status = Create(device.get(), max_blocks, out);
  if (status == ZX_OK) {
    (*out)->owned_device_ = std::move(device);
  }
  return status;
}

zx_status_t Bcache::Create(block_client::BlockDevice* device, uint32_t max_blocks,
                           std::unique_ptr<Bcache>* out) {
  std::unique_ptr<Bcache> bcache(new Bcache(device, max_blocks, kBlockSize));

  zx_status_t status = bcache->buffer_.Initialize(bcache.get(), 1, kBlockSize, "scratch-block");
  if (status != ZX_OK) {
    return status;
  }

  status = bcache->VerifyDeviceInfo();
  if (status != ZX_OK) {
    return status;
  }

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

zx_status_t Bcache::Create(std::unique_ptr<block_client::BlockDevice> device, uint32_t max_blocks,
                           std::unique_ptr<Bcache>* out, uint32_t block_size) {
  zx_status_t status = Create(device.get(), max_blocks, out, block_size);
  if (status == ZX_OK) {
    (*out)->owned_device_ = std::move(device);
  }
  return status;
}

zx_status_t Bcache::Create(block_client::BlockDevice* device, uint32_t max_blocks,
                           std::unique_ptr<Bcache>* out, uint32_t block_size) {
  std::unique_ptr<Bcache> bcache(new Bcache(device, max_blocks, block_size));

  zx_status_t status = bcache->buffer_.Initialize(bcache.get(), 1, block_size, "scratch-block");
  if (status != ZX_OK) {
    return status;
  }

  status = bcache->VerifyDeviceInfo();
  if (status != ZX_OK) {
    return status;
  }

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

uint32_t Bcache::DeviceBlockSize() const { return info_.block_size; }

Bcache::Bcache(block_client::BlockDevice* device, uint32_t max_blocks, uint32_t block_size)
    : max_blocks_(max_blocks), block_size_(block_size), device_(device) {}

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;
  }

  if (BlockSize() % info_.block_size != 0) {
    FX_LOGS(ERROR) << "minfs Block size not multiple of underlying block size: "
                   << info_.block_size;
    return ZX_ERR_BAD_STATE;
  }
  return ZX_OK;
}

void Bcache::Pause() { mutex_.lock(); }

void Bcache::Resume() { mutex_.unlock(); }

}  // namespace f2fs
