// 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 "src/storage/blobfs/host.h"

#include <fcntl.h>
#include <inttypes.h>
#include <lib/cksum.h>
#include <lib/stdcompat/span.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/status.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <zircon/assert.h>
#include <zircon/errors.h>
#include <zircon/status.h>

#include <cstddef>
#include <cstdint>
#include <memory>
#include <new>
#include <optional>
#include <string>
#include <utility>
#include <variant>
#include <vector>

#include <fbl/algorithm.h>
#include <fbl/array.h>
#include <fbl/macros.h>
#include <fbl/unique_fd.h>
#include <fs-host/common.h>
#include <safemath/checked_math.h>
#include <safemath/safe_conversions.h>

#include "src/lib/digest/digest.h"
#include "src/lib/digest/merkle-tree.h"
#include "src/lib/digest/node-digest.h"
#include "src/lib/storage/vfs/cpp/journal/initializer.h"
#include "src/lib/storage/vfs/cpp/transaction/transaction_handler.h"
#include "src/storage/blobfs/allocator/extent_reserver.h"
#include "src/storage/blobfs/allocator/host_allocator.h"
#include "src/storage/blobfs/allocator/node_reserver.h"
#include "src/storage/blobfs/blob_layout.h"
#include "src/storage/blobfs/common.h"
#include "src/storage/blobfs/compression/chunked.h"
#include "src/storage/blobfs/compression/compressor.h"
#include "src/storage/blobfs/compression/decompressor.h"
#include "src/storage/blobfs/compression_settings.h"
#include "src/storage/blobfs/format.h"
#include "src/storage/blobfs/fsck_host.h"
#include "src/storage/blobfs/iterator/allocated_extent_iterator.h"
#include "src/storage/blobfs/iterator/block_iterator.h"
#include "src/storage/blobfs/iterator/extent_iterator.h"
#include "src/storage/blobfs/iterator/node_populator.h"
#include "src/storage/blobfs/iterator/vector_extent_iterator.h"
#include "src/storage/blobfs/node_finder.h"

using digest::Digest;
using digest::MerkleTreeCreator;
using digest::MerkleTreeVerifier;

constexpr uint32_t kExtentCount = 5;

namespace blobfs {
namespace {

// TODO(markdittmer): Abstract choice of host compressor, decompressor and metadata flag to support
// choosing from multiple strategies. This has already been done in non-host code but host tools do
// not use |BlobCompressor| the same way.
using HostCompressor = ChunkedCompressor;
using HostDecompressor = ChunkedDecompressor;

constexpr CompressionSettings kCompressionSettings = {
    .compression_algorithm = CompressionAlgorithm::kChunked,
};

zx::status<> ReadBlocksWithOffset(int fd, uint64_t start_block, uint64_t block_count,
                                  off_t file_offset, void* data) {
  off_t off = safemath::checked_cast<off_t>(
      safemath::CheckAdd(file_offset,
                         safemath::CheckMul(start_block, kBlobfsBlockSize).ValueOrDie())
          .ValueOrDie());
  size_t size = safemath::CheckMul(block_count, kBlobfsBlockSize).ValueOrDie();
  auto udata = static_cast<uint8_t*>(data);
  while (size > 0) {
    ssize_t ret = pread(fd, udata, size, off);
    if (ret <= 0) {
      perror("failed read");
      FX_LOGS(ERROR) << "cannot read block " << start_block << " size:" << size << " off:" << off;
      return zx::error(ZX_ERR_IO);
    }
    size -= ret;
    off += ret;
    udata += ret;
  }
  return zx::ok();
}

zx::status<> ReadBlockWithOffset(int fd, uint64_t block_number, off_t file_offset, void* data) {
  return ReadBlocksWithOffset(fd, block_number, /*block_count=*/1, file_offset, data);
}

zx::status<> WriteBlocksWithOffset(int fd, uint64_t start_block, uint64_t block_count,
                                   off_t file_offset, const void* data) {
  off_t off = safemath::checked_cast<off_t>(
      safemath::CheckAdd(file_offset,
                         safemath::CheckMul(start_block, kBlobfsBlockSize).ValueOrDie())
          .ValueOrDie());
  size_t size = safemath::CheckMul(block_count, kBlobfsBlockSize).ValueOrDie();
  auto udata = static_cast<const uint8_t*>(data);
  while (size > 0) {
    ssize_t ret = pwrite(fd, udata, size, off);
    if (ret < 0) {
      perror("failed write");
      FX_LOGS(ERROR) << "cannot write block " << start_block << " size:" << size << " off:" << off;
      return zx::error(ZX_ERR_IO);
    }
    size -= ret;
    off += ret;
    udata += ret;
  }
  return zx::ok();
}

zx::status<> WriteBlocks(int fd, uint64_t start_block, uint64_t block_count, const void* data) {
  return WriteBlocksWithOffset(fd, start_block, block_count, /*file_offset=*/0, data);
}

zx::status<> WriteBlock(int fd, uint64_t block_number, const void* data) {
  return WriteBlocks(fd, block_number, /*block_count=*/1, data);
}

struct MerkleTreeInfo {
  static zx::status<MerkleTreeInfo> Create(cpp20::span<const uint8_t> data,
                                           BlobLayoutFormat blob_layout_format) {
    MerkleTreeCreator mtc;
    mtc.SetUseCompactFormat(blob_layout_format == BlobLayoutFormat::kCompactMerkleTreeAtEnd);
    if (zx_status_t status = mtc.SetDataLength(data.size()); status != ZX_OK) {
      return zx::error(status);
    }

    std::vector<uint8_t> merkle_tree(mtc.GetTreeLength(), 0);
    uint8_t root[digest::kSha256Length];
    if (zx_status_t status =
            mtc.SetTree(merkle_tree.data(), merkle_tree.size(), root, digest::kSha256Length);
        status != ZX_OK) {
      return zx::error(status);
    }
    if (zx_status_t status = mtc.Append(data.data(), data.size()); status != ZX_OK) {
      return zx::error(status);
    }
    MerkleTreeInfo mti;
    mti.digest = root;
    mti.merkle_tree = std::move(merkle_tree);
    return zx::ok(std::move(mti));
  }

  Digest digest;
  std::vector<uint8_t> merkle_tree;
};

zx::status<std::vector<uint8_t>> CompressData(cpp20::span<const uint8_t> data) {
  size_t max = HostCompressor::BufferMax(data.size());
  std::vector<uint8_t> compressed_data(max, 0);

  std::unique_ptr<HostCompressor> compressor;
  size_t output_limit;
  if (zx_status_t status =
          HostCompressor::Create(kCompressionSettings, data.size(), &output_limit, &compressor);
      status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to initialize blobfs compressor: " << status;
    return zx::error(status);
  }

  if (zx_status_t status = compressor->SetOutput(compressed_data.data(), max); status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to initialize blobfs compressor: " << status;
    return zx::error(status);
  }

  if (zx_status_t status = compressor->Update(data.data(), data.size()); status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to update blobfs compressor: " << status;
    return zx::error(status);
  }

  if (zx_status_t status = compressor->End(); status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to complete blobfs compressor: " << status;
    return zx::error(status);
  }

  compressed_data.resize(compressor->Size());
  return zx::ok(std::move(compressed_data));
}

// Returns ZX_OK and copies blobfs info_block_t, which is a block worth of data containing
// superblock, into |out_info_block| if the block read from fd belongs to blobfs.
zx_status_t blobfs_load_info_block(const fbl::unique_fd& fd, info_block_t* out_info_block,
                                   off_t start = 0, std::optional<off_t> end = std::nullopt) {
  info_block_t info_block;

  if (ReadBlockWithOffset(fd.get(), /*block_number=*/0, start,
                          reinterpret_cast<void*>(info_block.block))
          .is_error()) {
    return ZX_ERR_IO;
  }
  uint64_t block_count;
  if (zx_status_t status = GetBlockCount(fd.get(), &block_count); status != ZX_OK) {
    FX_LOGS(ERROR) << "cannot find end of underlying device";
    return status;
  }

  if (end &&
      ((block_count * kBlobfsBlockSize) < safemath::checked_cast<uint64_t>(end.value() - start))) {
    FX_LOGS(ERROR) << "Invalid file size " << safemath::checked_cast<uint64_t>(end.value() - start);
    return ZX_ERR_BAD_STATE;
  }
  if (zx_status_t status = CheckSuperblock(&info_block.info, block_count); status != ZX_OK) {
    FX_LOGS(ERROR) << "Info check failed " << status;
    return status;
  }

  memcpy(out_info_block, &info_block, sizeof(*out_info_block));

  return ZX_OK;
}

zx_status_t get_superblock(const fbl::unique_fd& fd, off_t start, std::optional<off_t> end,
                           Superblock* info) {
  info_block_t info_block;
  zx_status_t status;

  if ((status = blobfs_load_info_block(fd, &info_block, start, end)) != ZX_OK) {
    FX_LOGS(ERROR) << "Load of info block failed " << status;
    return status;
  }

  memcpy(info, &info_block.info, sizeof(info_block.info));
  return ZX_OK;
}

}  // namespace

zx::status<FileMapping> FileMapping::Create(int fd) {
  struct stat s;
  if (fstat(fd, &s) < 0) {
    return zx::error(ZX_ERR_BAD_STATE);
  }
  if (s.st_size == 0) {
    // Empty files can't be mapped.
    return zx::ok(FileMapping(nullptr, 0));
  }

  void* data = mmap(nullptr, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  if (data == MAP_FAILED) {
    return zx::error(ZX_ERR_BAD_STATE);
  }
  return zx::ok(FileMapping(data, s.st_size));
}

FileMapping::FileMapping(FileMapping&& other) noexcept
    : data_(other.data_), length_(other.length_) {
  other.data_ = nullptr;
  other.length_ = 0;
}

FileMapping& FileMapping::operator=(FileMapping&& other) noexcept {
  data_ = other.data_;
  length_ = other.length_;
  other.data_ = nullptr;
  other.length_ = 0;
  return *this;
}

FileMapping::~FileMapping() {
  if (data_ != nullptr) {
    munmap(data_, length_);
  }
}

zx::status<BlobInfo> BlobInfo::CreateCompressed(int fd, BlobLayoutFormat blob_layout_format,
                                                std::filesystem::path file_path) {
  zx::status<BlobInfo> blob_info = CreateUncompressed(fd, blob_layout_format, std::move(file_path));
  if (blob_info.is_error()) {
    return blob_info;
  }

  cpp20::span<const uint8_t> data = blob_info->GetData();
  if (data.size() <= kCompressionSizeThresholdBytes) {
    // The blob is already small and compressing wouldn't save any space, leave the blob
    // uncompressed.
    return blob_info;
  }

  zx::status<std::vector<uint8_t>> compressed_data = CompressData(data);
  if (compressed_data.is_error()) {
    return compressed_data.take_error();
  }

  zx::status<std::unique_ptr<BlobLayout>> compressed_blob_layout = BlobLayout::CreateFromSizes(
      blob_layout_format, data.size(), compressed_data->size(), kBlobfsBlockSize);
  if (compressed_blob_layout.is_error()) {
    return compressed_blob_layout.take_error();
  }

  if (compressed_blob_layout->TotalBlockCount() >= blob_info->GetBlobLayout().TotalBlockCount()) {
    // Compressing the blob didn't save any blocks, leave the blob uncompressed.
    return blob_info;
  }
  // Replace the uncompressed data with the compressed data.
  blob_info->blob_layout_ = std::move(compressed_blob_layout).value();
  blob_info->blob_data_ = std::move(compressed_data).value();

  return blob_info;
}

zx::status<BlobInfo> BlobInfo::CreateUncompressed(int fd, BlobLayoutFormat blob_layout_format,
                                                  std::filesystem::path file_path) {
  BlobInfo blob_info;
  blob_info.src_file_path_ = std::move(file_path);

  zx::status<FileMapping> file_mapping = FileMapping::Create(fd);
  if (file_mapping.is_error()) {
    return file_mapping.take_error();
  }

  cpp20::span<const uint8_t> data = file_mapping->data();
  zx::status<MerkleTreeInfo> merkle_tree_info = MerkleTreeInfo::Create(data, blob_layout_format);
  if (merkle_tree_info.is_error()) {
    return merkle_tree_info.take_error();
  }
  blob_info.merkle_tree_ = std::move(merkle_tree_info->merkle_tree);
  blob_info.digest_ = std::move(merkle_tree_info->digest);

  auto blob_layout =
      BlobLayout::CreateFromSizes(blob_layout_format, data.size(), data.size(), kBlobfsBlockSize);
  if (blob_layout.is_error()) {
    return blob_layout.take_error();
  }
  blob_info.blob_layout_ = std::move(blob_layout).value();

  blob_info.blob_data_.emplace<FileMapping>(std::move(file_mapping).value());

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

zx_status_t ReadBlock(int fd, uint64_t block_number, void* data) {
  return ReadBlockWithOffset(fd, block_number, /*file_offset=*/0, data).status_value();
}

zx_status_t GetBlockCount(int fd, uint64_t* out) {
  struct stat s;
  if (fstat(fd, &s) < 0) {
    return ZX_ERR_BAD_STATE;
  }
  *out = s.st_size / kBlobfsBlockSize;
  return ZX_OK;
}

int Mkfs(int fd, uint64_t block_count, const FilesystemOptions& options) {
  Superblock info;
  if (zx_status_t status = InitializeSuperblock(block_count, options, &info); status != ZX_OK) {
    return status;
  }
  if (zx_status_t status = CheckSuperblock(&info, block_count); status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to initialize superblock: " << status;
    return -1;
  }
  uint64_t block_bitmap_blocks = BlockMapBlocks(info);
  uint64_t node_map_blocks = NodeMapBlocks(info);

  RawBitmap block_bitmap;
  if (block_bitmap.Reset(block_bitmap_blocks * kBlobfsBlockBits)) {
    FX_LOGS(ERROR) << "Couldn't allocate blobfs block map";
    return -1;
  }
  if (block_bitmap.Shrink(info.data_block_count)) {
    FX_LOGS(ERROR) << "Couldn't shrink blobfs block map";
    return -1;
  }

  // Reserve first |kStartBlockMinimum| data blocks
  block_bitmap.Set(0, kStartBlockMinimum);

  // All in-memory structures have been created successfully. Dump everything to disk.
  // Initialize on-disk journal.
  fs::WriteBlocksFn write_blocks_fn = [fd, &info](cpp20::span<const uint8_t> buffer,
                                                  uint64_t block_offset, uint64_t block_count) {
    ZX_ASSERT((block_offset + block_count) <= JournalBlocks(info));
    ZX_ASSERT(buffer.size() >= (block_count * kBlobfsBlockSize));
    return WriteBlocks(fd, JournalStartBlock(info) + block_offset, block_count, buffer.data())
        .status_value();
  };
  if (zx_status_t status = fs::MakeJournal(JournalBlocks(info), write_blocks_fn); status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to write journal block";
    return -1;
  }

  // Write the root block to disk.
  static_assert(kBlobfsBlockSize == sizeof(info));
  if (WriteBlock(fd, 0, &info).is_error()) {
    FX_LOGS(ERROR) << "Failed to write Superblock";
    return -1;
  }

  // Write allocation bitmap to disk.
  if (WriteBlocks(fd, BlockMapStartBlock(info), block_bitmap_blocks,
                  block_bitmap.StorageUnsafe()->GetData())
          .is_error()) {
    FX_LOGS(ERROR) << "Failed to write blockmap block " << block_bitmap_blocks;
    return -1;
  }

  // Write node map to disk.
  size_t map_length = node_map_blocks * kBlobfsBlockSize;
  void* blocks = mmap(nullptr, map_length, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);
  if (blocks == MAP_FAILED) {
    FX_LOGS(ERROR) << "failed to map zeroes for inode map of size " << map_length;
    return -1;
  }
  if (WriteBlocks(fd, NodeMapStartBlock(info), node_map_blocks, blocks).is_error()) {
    FX_LOGS(ERROR) << "failed writing inode map";
    munmap(blocks, map_length);
    return -1;
  }
  if (munmap(blocks, map_length) != 0) {
    FX_LOGS(ERROR) << "failed unmap inode map";
    return -1;
  }

  FX_LOGS(DEBUG) << "mkfs success";
  return 0;
}

zx_status_t UsedDataSize(const fbl::unique_fd& fd, uint64_t* out_size, off_t start,
                         std::optional<off_t> end) {
  Superblock info;
  zx_status_t status;

  if ((status = get_superblock(fd, start, end, &info)) != ZX_OK) {
    return status;
  }

  *out_size = info.alloc_block_count * info.block_size;
  return ZX_OK;
}

zx_status_t UsedInodes(const fbl::unique_fd& fd, uint64_t* out_inodes, off_t start,
                       std::optional<off_t> end) {
  Superblock info;
  zx_status_t status;

  if ((status = get_superblock(fd, start, end, &info)) != ZX_OK) {
    return status;
  }

  *out_inodes = info.alloc_inode_count;
  return ZX_OK;
}

zx_status_t UsedSize(const fbl::unique_fd& fd, uint64_t* out_size, off_t start,
                     std::optional<off_t> end) {
  Superblock info;
  zx_status_t status;

  if ((status = get_superblock(fd, start, end, &info)) != ZX_OK) {
    return status;
  }

  *out_size = (TotalNonDataBlocks(info) + info.alloc_block_count) * info.block_size;
  return ZX_OK;
}

zx_status_t blobfs_create(std::unique_ptr<Blobfs>* out, fbl::unique_fd fd) {
  info_block_t info_block;
  zx_status_t status;

  if ((status = blobfs_load_info_block(fd, &info_block)) != ZX_OK) {
    return status;
  }

  fbl::Array<size_t> extent_lengths(new size_t[kExtentCount], kExtentCount);

  if (info_block.info.flags & kBlobFlagFVM) {
    // The image is assumed to be a sparse file containing an FVM-formatted blobfs image with the
    // various metadata regions at their correct offsets. We just consider the "length" of each
    // extent to be the maximum possible length (i.e.  the number of blocks up to the offset of the
    // next region).
    extent_lengths[0] = BlockMapStartBlock(info_block.info) * kBlobfsBlockSize;
    extent_lengths[1] = (NodeMapStartBlock(info_block.info) - BlockMapStartBlock(info_block.info)) *
                        kBlobfsBlockSize;
    extent_lengths[2] = (JournalStartBlock(info_block.info) - NodeMapStartBlock(info_block.info)) *
                        kBlobfsBlockSize;
    extent_lengths[3] =
        (DataStartBlock(info_block.info) - JournalStartBlock(info_block.info)) * kBlobfsBlockSize;
    extent_lengths[4] = DataBlocks(info_block.info) * kBlobfsBlockSize;
  } else {
    extent_lengths[0] = BlockMapStartBlock(info_block.info) * kBlobfsBlockSize;
    extent_lengths[1] = BlockMapBlocks(info_block.info) * kBlobfsBlockSize;
    extent_lengths[2] = NodeMapBlocks(info_block.info) * kBlobfsBlockSize;
    extent_lengths[3] = JournalBlocks(info_block.info) * kBlobfsBlockSize;
    extent_lengths[4] = DataBlocks(info_block.info) * kBlobfsBlockSize;
  }

  auto blobfs = Blobfs::Create(std::move(fd), 0, info_block, extent_lengths);
  if (blobfs.is_error()) {
    FX_LOGS(ERROR) << "mount failed; could not create blobfs";
    return blobfs.status_value();
  }

  *out = std::move(blobfs).value();
  return ZX_OK;
}

zx_status_t blobfs_create_sparse(std::unique_ptr<Blobfs>* out, fbl::unique_fd fd, off_t start,
                                 off_t end, const std::vector<size_t>& extent_vector) {
  if (start >= end) {
    FX_LOGS(ERROR) << "Insufficient space allocated";
    return ZX_ERR_INVALID_ARGS;
  }
  if (extent_vector.size() != kExtentCount) {
    FX_LOGS(ERROR) << "Incorrect number of extents";
    return ZX_ERR_INVALID_ARGS;
  }

  info_block_t info_block;
  zx_status_t status;

  if ((status = blobfs_load_info_block(fd, &info_block, start, end)) != ZX_OK) {
    return status;
  }

  fbl::Array<size_t> extent_lengths(new size_t[kExtentCount], kExtentCount);

  extent_lengths[0] = extent_vector[0];
  extent_lengths[1] = extent_vector[1];
  extent_lengths[2] = extent_vector[2];
  extent_lengths[3] = extent_vector[3];
  extent_lengths[4] = extent_vector[4];

  auto blobfs = Blobfs::Create(std::move(fd), start, info_block, extent_lengths);
  if (blobfs.is_error()) {
    FX_LOGS(ERROR) << "mount failed; could not create blobfs";
    return blobfs.status_value();
  }

  *out = std::move(blobfs).value();
  return ZX_OK;
}

zx_status_t blobfs_fsck(fbl::unique_fd fd, off_t start, off_t end,
                        const std::vector<size_t>& extent_lengths) {
  std::unique_ptr<Blobfs> blob;
  zx_status_t status;
  if ((status = blobfs_create_sparse(&blob, std::move(fd), start, end, extent_lengths)) != ZX_OK) {
    return status;
  }
  if ((status = Fsck(blob.get())) != ZX_OK) {
    return status;
  }
  return ZX_OK;
}

Blobfs::Blobfs(fbl::unique_fd fd, off_t offset, const info_block_t& info_block,
               const fbl::Array<size_t>& extent_lengths)
    : blockfd_(std::move(fd)), offset_(offset) {
  ZX_ASSERT(extent_lengths.size() == kExtentCount);
  memcpy(&info_block_, info_block.block, kBlobfsBlockSize);

  block_map_start_block_ = extent_lengths[0] / kBlobfsBlockSize;
  block_map_block_count_ = extent_lengths[1] / kBlobfsBlockSize;
  node_map_start_block_ = block_map_start_block_ + block_map_block_count_;
  node_map_block_count_ = extent_lengths[2] / kBlobfsBlockSize;
  journal_start_block_ = node_map_start_block_ + node_map_block_count_;
  journal_block_count_ = extent_lengths[3] / kBlobfsBlockSize;
  data_start_block_ = journal_start_block_ + journal_block_count_;
  data_block_count_ = extent_lengths[4] / kBlobfsBlockSize;
}

zx::status<std::unique_ptr<Blobfs>> Blobfs::Create(fbl::unique_fd blockfd_, off_t offset,
                                                   const info_block_t& info_block,
                                                   const fbl::Array<size_t>& extent_lengths) {
  if (zx_status_t status = CheckSuperblock(&info_block.info, TotalBlocks(info_block.info));
      status != ZX_OK) {
    FX_LOGS(ERROR) << "Check info failure";
    return zx::error(status);
  }

  ZX_ASSERT(extent_lengths.size() == kExtentCount);

  for (unsigned i = 0; i < 3; i++) {
    if (extent_lengths[i] % kBlobfsBlockSize) {
      return zx::error(ZX_ERR_INVALID_ARGS);
    }
  }

  auto fs =
      std::unique_ptr<Blobfs>(new Blobfs(std::move(blockfd_), offset, info_block, extent_lengths));

  auto node_map = fs->LoadNodeMap();
  if (node_map.is_error()) {
    FX_LOGS(ERROR) << "Failed to load node map";
    return node_map.take_error();
  }
  fs->node_map_ = std::move(node_map).value();

  auto block_bitmap = fs->LoadBlockBitmap();
  if (block_bitmap.is_error()) {
    FX_LOGS(ERROR) << "Failed to load bitmaps";
    return block_bitmap.take_error();
  }

  auto host_allocator =
      HostAllocator::Create(std::move(block_bitmap).value(), cpp20::span<Inode>(fs->node_map_));
  if (host_allocator.is_error()) {
    return host_allocator.take_error();
  }
  fs->allocator_ = std::move(host_allocator).value();

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

zx::status<RawBitmap> Blobfs::LoadBlockBitmap() {
  RawBitmap block_bitmap;
  if (zx_status_t status = block_bitmap.Reset(block_map_block_count_ * kBlobfsBlockBits);
      status != ZX_OK) {
    return zx::error(status);
  }
  if (zx_status_t status = block_bitmap.Shrink(info_.data_block_count); status != ZX_OK) {
    return zx::error(status);
  }
  if (zx::status<> status = ReadBlocks(block_map_start_block_, block_map_block_count_,
                                       block_bitmap.StorageUnsafe()->GetData());
      status.is_error()) {
    return status.take_error();
  }
  return zx::ok(std::move(block_bitmap));
}

zx::status<std::vector<Inode>> Blobfs::LoadNodeMap() {
  const size_t nodes_to_load = fbl::round_up(Info().inode_count, kBlobfsInodesPerBlock);
  std::vector<Inode> node_map(nodes_to_load);
  if (zx::status<> status =
          ReadBlocks(node_map_start_block_, NodeMapBlocks(info_), node_map.data());
      status.is_error()) {
    return status.take_error();
  }
  return zx::ok(std::move(node_map));
}

zx::status<uint32_t> Blobfs::FindInodeByDigest(const Digest& digest) {
  for (uint32_t node_index = 0; node_index < info_.inode_count; ++node_index) {
    Inode& inode = node_map_[node_index];
    if (inode.header.IsAllocated() && inode.header.IsInode() && digest == inode.merkle_root_hash) {
      return zx::ok(node_index);
    }
  }
  return zx::error(ZX_ERR_NOT_FOUND);
}

zx::status<> Blobfs::AddBlob(const BlobInfo& blob_info) {
  const BlobLayout& blob_layout = blob_info.GetBlobLayout();
  if (blob_layout.Format() != GetBlobLayoutFormat(Info())) {
    return zx::error(ZX_ERR_INVALID_ARGS);
  }

  // Make sure that the blob hasn't already been added.
  if (auto existing_node = FindInodeByDigest(blob_info.GetDigest());
      existing_node.status_value() != ZX_ERR_NOT_FOUND) {
    if (existing_node.is_ok()) {
      FX_LOGS(ERROR) << "Blob already exists " << blob_info.GetDigest().ToString();
      return zx::error(ZX_ERR_ALREADY_EXISTS);
    }
    return existing_node.take_error();
  }

  // Reserve blocks for the blob's data.
  std::vector<ReservedExtent> extents;
  if (zx_status_t status = allocator_->ReserveBlocks(blob_layout.TotalBlockCount(), &extents);
      status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to reserve enough blocks: " << status;
    return zx::error(status);
  }
  if (extents.size() > kMaxBlobExtents) {
    FX_LOGS(ERROR) << "Block reservation requires too many extents (" << extents.size() << " vs "
                   << kMaxBlobExtents << " max)";
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }

  // Write out the blob's data.
  if (zx::status<> status = WriteData(blob_info, extents); status.is_error()) {
    FX_LOGS(ERROR) << "Blobfs WriteData failed " << status.status_value();
    return status;
  }

  // Update the block bitmap and write it out.
  for (const ReservedExtent& reserved_extent : extents) {
    allocator_->MarkBlocksAllocated(reserved_extent);
    if (zx::status<> status = WriteBlockBitmap(reserved_extent.extent()); status.is_error()) {
      FX_LOGS(ERROR) << "Blobfs WriteBlockBitmap failed " << status.status_value();
      return status;
    }
  }

  // Reserve the inode + extent containers to hold all of the extents.
  uint32_t node_count =
      NodePopulator::NodeCountForExtents(safemath::checked_cast<ExtentCountType>(extents.size()));
  std::vector<ReservedNode> nodes;
  if (zx_status_t status = allocator_->ReserveNodes(node_count, &nodes); status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to reserve enough nodes: " << status;
    return zx::error(status);
  }
  std::vector<uint32_t> node_indices;
  node_indices.reserve(nodes.size());
  for (const auto& node : nodes) {
    node_indices.push_back(node.index());
  }

  // Place the extents into the inode and container nodes.
  auto on_node = [](uint32_t node_index) {};
  auto on_extent = [](ReservedExtent& reserved_extent) {
    return NodePopulator::IterationCommand::Continue;
  };
  NodePopulator node_populator(allocator_.get(), std::move(extents), std::move(nodes));
  if (zx_status_t status = node_populator.Walk(on_node, on_extent); status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to populate nodes with extents: " << status;
    return zx::error(status);
  }

  // Fill in the inode.
  auto inode = GetNode(node_indices[0]);
  if (inode.is_error()) {
    return inode.take_error();
  }
  inode->blob_size = blob_layout.FileSize();
  inode->block_count = blob_layout.TotalBlockCount();
  blob_info.GetDigest().CopyTo(inode->merkle_root_hash);
  inode->header.flags |=
      (blob_info.IsCompressed() ? HostCompressor::InodeHeaderCompressionFlags() : 0);

  // Write out all nodes.
  // The nodes can't be in written in |on_node| because the NodePopulator modifies the nodes after
  // calling |on_node|.
  for (uint32_t node_index : node_indices) {
    if (zx::status<> status = WriteNode(node_index); status.is_error()) {
      FX_LOGS(ERROR) << "Blobfs WriteNode failed " << status.status_value();
      return status;
    }
  }

  // Update and write out the Superblock.
  info_.alloc_block_count += blob_layout.TotalBlockCount();
  info_.alloc_inode_count += node_count;
  if (zx::status<> status = WriteInfo(); status.is_error()) {
    FX_LOGS(ERROR) << "Blobfs WriteInfo failed " << status.status_value();
    return status;
  }

  return zx::ok();
}

zx::status<> Blobfs::WriteBlockBitmap(const Extent& extent) {
  uint64_t block_bitmap_start_block = extent.Start() / kBlobfsBlockBits;
  uint64_t block_bitmap_end_block =
      fbl::round_up(extent.Start() + extent.Length(), kBlobfsBlockBits) / kBlobfsBlockBits;
  const void* bmstart = allocator_->GetBlockBitmapData();
  const void* data = fs::GetBlock(kBlobfsBlockSize, bmstart, block_bitmap_start_block);
  uint64_t absolute_block_number = block_map_start_block_ + block_bitmap_start_block;
  uint64_t block_count = block_bitmap_end_block - block_bitmap_start_block;
  return WriteBlocks(absolute_block_number, block_count, data);
}

zx::status<> Blobfs::WriteNode(uint32_t node_index) {
  uint64_t node_block = node_index / kBlobfsInodesPerBlock;
  return WriteBlock(node_map_start_block_ + node_block,
                    fs::GetBlock(kBlobfsBlockSize, node_map_.data(), node_block));
}

zx::status<> Blobfs::WriteData(const BlobInfo& blob_info,
                               const std::vector<ReservedExtent>& extents) {
  const BlobLayout& blob_layout = blob_info.GetBlobLayout();
  if (blob_layout.TotalBlockCount() == 0) {
    // Nothing to write.
    return zx::ok();
  }
  // Allocate a new buffer to hold both the data and Merkle tree together.  The data and Merkle tree
  // may not be block multiples in size which makes writing them separately in terms of blocks
  // difficult, also the data and Merkle tree may share a block.  Creating a new buffer to hold both
  // uses more memory but makes writing the blob significantly easier.
  uint64_t block_size = GetBlockSize();
  uint64_t buf_size = block_size * blob_layout.TotalBlockCount();
  auto buf = std::make_unique<uint8_t[]>(size_t{blob_layout.TotalBlockCount()} * GetBlockSize());
  // Zero the entire buffer instead of trying to calculate where the data and Merkle tree won't be.
  memset(buf.get(), 0, buf_size);

  // Copy the data to the buffer.
  uint64_t data_offset = block_size * blob_layout.DataBlockOffset();
  cpp20::span<const uint8_t> data = blob_info.GetData();
  memcpy(buf.get() + data_offset, data.data(), data.size());

  // |merkle_data| will be null when the blob size is less than or equal to the Merkle tree node
  // size.
  cpp20::span<const uint8_t> merkle_tree = blob_info.GetMerkleTree();
  if (!merkle_tree.empty()) {
    // Copy the Merkle tree to the buffer.
    uint64_t merkle_offset = block_size * blob_layout.MerkleTreeBlockOffset() +
                             blob_layout.MerkleTreeOffsetWithinBlockOffset();
    memcpy(buf.get() + merkle_offset, merkle_tree.data(), merkle_tree.size());
  }

  VectorExtentIterator extent_iter(extents);
  uint64_t buf_block_offset = 0;
  while (!extent_iter.Done()) {
    zx::status<const Extent*> extent = extent_iter.Next();
    if (extent.is_error()) {
      return extent.take_error();
    }

    const void* extent_data = fs::GetBlock(GetBlockSize(), buf.get(), buf_block_offset);
    if (zx::status<> status =
            WriteBlocks(data_start_block_ + (*extent)->Start(), (*extent)->Length(), extent_data);
        status.is_error()) {
      FX_LOGS(ERROR) << "Failed to write extent data: " << status.status_value();
      return status;
    }
    buf_block_offset += (*extent)->Length();
  }

  return zx::ok();
}

zx::status<> Blobfs::WriteInfo() { return WriteBlock(0, info_block_); }

zx::status<> Blobfs::ReadBlocks(uint64_t start_block, uint64_t block_count, void* data) {
  return ReadBlocksWithOffset(blockfd_.get(), start_block, block_count, offset_, data);
}

zx::status<> Blobfs::ReadBlock(uint64_t block_number, void* data) {
  return ReadBlocks(block_number, /*block_count=*/1, data);
}

zx::status<> Blobfs::WriteBlocks(uint64_t start_block, uint64_t block_count, const void* data) {
  return WriteBlocksWithOffset(blockfd_.get(), start_block, block_count, offset_, data);
}

zx::status<> Blobfs::WriteBlock(uint64_t block_number, const void* data) {
  return WriteBlocks(block_number, /*block_count=*/1, data);
}

zx::status<InodePtr> Blobfs::GetNode(uint32_t node_index) {
  return allocator_->GetNode(node_index);
}

bool Blobfs::CheckBlocksAllocated(uint64_t start_block, uint64_t end_block,
                                  uint64_t* first_unset) const {
  return allocator_->CheckBlocksAllocated(start_block, end_block, first_unset);
}

zx::status<> Blobfs::ReadBlocksForInode(uint32_t node_index, uint32_t start_block,
                                        uint32_t block_count, uint8_t* data) {
  zx::status<AllocatedExtentIterator> extent_iterator_or =
      AllocatedExtentIterator::Create(GetNodeFinder(), node_index);
  if (extent_iterator_or.is_error()) {
    return extent_iterator_or.take_error();
  }
  BlockIterator iter(
      std::make_unique<AllocatedExtentIterator>(std::move(extent_iterator_or.value())));
  if (zx_status_t status = IterateToBlock(&iter, start_block); status != ZX_OK) {
    return zx::error(status);
  }
  std::vector<std::pair<uint64_t, uint32_t>> ranges;
  zx_status_t status =
      StreamBlocks(&iter, block_count, [&ranges](int64_t, uint64_t start, uint32_t length) {
        ranges.emplace_back(start, length);
        return ZX_OK;
      });
  if (status != ZX_OK) {
    return zx::error(status);
  }
  size_t block_offset = 0;
  for (auto range : ranges) {
    zx::status<> status = ReadBlocks(data_start_block_ + range.first, range.second,
                                     &data[block_offset * GetBlockSize()]);
    if (status.is_error()) {
      return status;
    }
    block_offset += range.second;
  }
  return zx::ok();
}

fpromise::result<std::vector<uint8_t>, std::string> Blobfs::LoadDataAndVerifyBlob(
    uint32_t node_index) {
  auto inode_ptr = GetNode(node_index);
  if (inode_ptr.is_error()) {
    return fpromise::error("Failed to get Inode index " + std::to_string(node_index) + ": " +
                           std::to_string(inode_ptr.status_value()));
  }
  Inode inode = *inode_ptr.value();
  const uint32_t block_size = GetBlockSize();
  zx_status_t status;
  auto make_error = [&](const std::string& error) {
    digest::Digest digest(inode.merkle_root_hash);
    auto digest_str = digest.ToString();
    return fpromise::error("Blob with merkle root hash of " +
                           std::string(digest_str.data(), digest_str.length()) +
                           " had errors. More specifically: " + error);
  };

  auto blob_layout =
      blobfs::BlobLayout::CreateFromInode(GetBlobLayoutFormat(Info()), inode, block_size);
  if (blob_layout.is_error()) {
    return make_error("Failed to create blob layout with status " +
                      std::to_string(blob_layout.status_value()));
  }

  std::vector<uint8_t> merkle_tree_blocks(blob_layout->MerkleTreeBlockAlignedSize(), 0);
  std::vector<uint8_t> data_blocks(blob_layout->DataBlockAlignedSize(), 0);
  if (blob_layout->MerkleTreeBlockAlignedSize() > 0) {
    if (zx::status<> status =
            ReadBlocksForInode(node_index, blob_layout->MerkleTreeBlockOffset(),
                               blob_layout->MerkleTreeBlockCount(), merkle_tree_blocks.data());
        status.is_error()) {
      return make_error("Failed to read in merkle tree blocks: " +
                        std::to_string(status.status_value()));
    }
  }
  if (blob_layout->DataBlockAlignedSize() > 0) {
    if (zx::status<> status = ReadBlocksForInode(node_index, blob_layout->DataBlockOffset(),
                                                 blob_layout->DataBlockCount(), data_blocks.data());
        status.is_error()) {
      return make_error("Failed to read in data blocks: " + std::to_string(status.status_value()));
    }
  }

  // Decompress the data if necessary.
  if (inode.header.flags & HostCompressor::InodeHeaderCompressionFlags()) {
    size_t file_size = inode.blob_size;
    std::vector<uint8_t> uncompressed_data(file_size, 0);
    HostDecompressor decompressor;
    if ((status = decompressor.Decompress(uncompressed_data.data(), &file_size, data_blocks.data(),
                                          blob_layout->DataSizeUpperBound())) != ZX_OK) {
      return make_error("Failed to decompress with status " + std::to_string(status));
    }
    if (file_size != inode.blob_size) {
      return make_error("Decompressed blob size of " + std::to_string(file_size) +
                        " mismatch with blob inode expected size of " +
                        std::to_string(inode.blob_size));
    }
    // Replace the compressed data with the uncompressed data.
    data_blocks = std::move(uncompressed_data);
  }

  // Verify the contents of the blob.
  uint8_t* merkle_tree_ptr =
      merkle_tree_blocks.empty()
          ? nullptr
          : &merkle_tree_blocks[blob_layout->MerkleTreeOffsetWithinBlockOffset()];
  MerkleTreeVerifier mtv;
  mtv.SetUseCompactFormat(blobfs::ShouldUseCompactMerkleTreeFormat(blob_layout->Format()));
  if ((status = mtv.SetDataLength(inode.blob_size)) != ZX_OK ||
      (status = mtv.SetTree(merkle_tree_ptr, mtv.GetTreeLength(), inode.merkle_root_hash,
                            sizeof(inode.merkle_root_hash))) != ZX_OK ||
      (status = mtv.Verify(data_blocks.data(), inode.blob_size, 0)) != ZX_OK) {
    return make_error("Verification failed with status " + std::to_string(status));
  }

  // Remove trailing block alignment.
  data_blocks.resize(inode.blob_size, 0);

  return fpromise::ok(std::move(data_blocks));
}

zx_status_t Blobfs::LoadAndVerifyBlob(uint32_t node_index) {
  auto load_result = LoadDataAndVerifyBlob(node_index);
  if (load_result.is_error()) {
    FX_LOGS(ERROR) << load_result.error();
    return ZX_ERR_INTERNAL;
  }
  return ZX_OK;
}

uint32_t Blobfs::GetBlockSize() const { return Info().block_size; }

fpromise::result<void, std::string> Blobfs::VisitBlobs(BlobVisitor visitor) {
  for (uint32_t inode_index = 0, allocated_nodes = 0;
       inode_index < info_.inode_count && allocated_nodes < info_.alloc_inode_count;
       ++inode_index) {
    auto inode = GetNode(safemath::checked_cast<uint32_t>(inode_index));
    if (inode.is_error()) {
      return fpromise::error("Failed to retrieve inode.");
    }
    if (!inode->header.IsAllocated() || !inode->header.IsInode()) {
      continue;
    }

    allocated_nodes++;
    auto load_result = LoadDataAndVerifyBlob(safemath::checked_cast<uint32_t>(inode_index));
    if (load_result.is_error()) {
      return load_result.take_error_result();
    }
    BlobView view = {
        .merkle_hash = cpp20::span<const uint8_t>(inode->merkle_root_hash),
        .blob_contents = load_result.value(),
    };

    auto visitor_result = visitor(view);
    if (visitor_result.is_error()) {
      return visitor_result.take_error_result();
    }
  }
  return fpromise::ok();
}

fpromise::result<void, std::string> ExportBlobs(int output_dir, Blobfs& fs) {
  return fs.VisitBlobs([output_dir](Blobfs::BlobView view) -> fpromise::result<void, std::string> {
    uint8_t hash[digest::kSha256Length];
    memcpy(hash, view.merkle_hash.data(), digest::kSha256Length);
    auto blob_name = digest::Digest(hash).ToString();
    fbl::unique_fd file(openat(output_dir, blob_name.c_str(), O_CREAT | O_RDWR, 0644));
    if (!file.is_valid()) {
      return fpromise::error(
          "Failed to create blob file" + std::string(blob_name.c_str()) +
          "(merkle root digest) in output dir. More specifically: " + strerror(errno));
    }

    size_t written_bytes = 0;
    ssize_t write_result = 0;
    while (written_bytes < view.blob_contents.size()) {
      write_result = write(file.get(), &view.blob_contents[written_bytes],
                           view.blob_contents.size() - written_bytes);
      if (write_result < 0) {
        return fpromise::error(
            "Failed to write blob " + std::string(blob_name.c_str()) +
            "(merkle root digest) contents in output file. More specifically: " + strerror(errno));
      }
      written_bytes += write_result;
    }

    return fpromise::ok();
  });
}

zx::status<std::unique_ptr<Superblock>> Blobfs::ReadBackupSuperblock() {
  auto superblock = std::make_unique<Superblock>();
  if (zx::status<> status = ReadBlock(kFVMBackupSuperblockOffset, superblock.get());
      status.is_error()) {
    return status.take_error();
  }
  return zx::ok(std::move(superblock));
}

}  // namespace blobfs
