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

#include <inttypes.h>

#include <utility>

#include <fs/trace.h>

#ifdef __Fuchsia__

#include <fuchsia/hardware/block/volume/c/fidl.h>
#include <zircon/status.h>

#include <fs/journal/replay.h>

#else

#include <blobfs/host.h>

#endif

#include "iterator/allocated-extent-iterator.h"
#include "iterator/extent-iterator.h"

namespace blobfs {

void BlobfsChecker::TraverseInodeBitmap() {
  for (unsigned n = 0; n < blobfs_->info_.inode_count; n++) {
    Inode* inode = blobfs_->GetNode(n);
    if (inode->header.IsAllocated()) {
      alloc_inodes_++;
      if (inode->header.IsExtentContainer()) {
        // TODO(smklein): sanity check these containers.
        continue;
      }

      bool valid = true;

      AllocatedExtentIterator extents = AllocatedExtentIterator(blobfs_->GetNodeFinder(), n);
      while (!extents.Done()) {
        const Extent* extent;
        zx_status_t status = extents.Next(&extent);
        if (status != ZX_OK) {
          FS_TRACE_ERROR("check: Failed to acquire extent %u within inode %u.\n",
                         extents.ExtentIndex(), n);
          valid = false;
          break;
        }

        uint64_t start_block = extent->Start();
        uint64_t end_block = extent->Start() + extent->Length();
        uint64_t first_unset = 0;
        if (!blobfs_->CheckBlocksAllocated(start_block, end_block, &first_unset)) {
          FS_TRACE_ERROR("check: ino %u using blocks [%" PRIu64 ", %" PRIu64
                         "). "
                         "Not fully allocated in block bitmap; first unset @%" PRIu64 "\n",
                         n, start_block, end_block, first_unset);
          valid = false;
        }
        inode_blocks_ += extent->Length();
      }

      if (blobfs_->LoadAndVerifyBlob(n) != ZX_OK) {
        FS_TRACE_ERROR("check: detected inode %u with bad state\n", n);
        valid = false;
      }
      if (!valid) {
        error_blobs_++;
      }
    }
  }
}

void BlobfsChecker::TraverseBlockBitmap() {
  for (uint64_t n = 0; n < blobfs_->info_.data_block_count; n++) {
    if (blobfs_->CheckBlocksAllocated(n, n + 1)) {
      alloc_blocks_++;
    }
  }
}

zx_status_t BlobfsChecker::CheckAllocatedCounts() const {
  zx_status_t status = ZX_OK;
  if (alloc_blocks_ != blobfs_->info_.alloc_block_count) {
    FS_TRACE_ERROR("check: incorrect allocated block count %" PRIu64 " (should be %u)\n",
                   blobfs_->info_.alloc_block_count, alloc_blocks_);
    status = ZX_ERR_BAD_STATE;
  }

  if (alloc_blocks_ < kStartBlockMinimum) {
    FS_TRACE_ERROR("check: allocated blocks (%u) are less than minimum (%" PRIu64 ")\n",
                   alloc_blocks_, kStartBlockMinimum);
    status = ZX_ERR_BAD_STATE;
  }

  if (inode_blocks_ + kStartBlockMinimum != alloc_blocks_) {
    FS_TRACE_ERROR(
        "check: bitmap allocated blocks (%u) do not match inode allocated blocks "
        "(%" PRIu64 ")\n",
        alloc_blocks_, inode_blocks_ + kStartBlockMinimum);
    status = ZX_ERR_BAD_STATE;
  }

  if (alloc_inodes_ != blobfs_->info_.alloc_inode_count) {
    FS_TRACE_ERROR("check: incorrect allocated inode count %" PRIu64 " (should be %u)\n",
                   blobfs_->info_.alloc_inode_count, alloc_inodes_);
    status = ZX_ERR_BAD_STATE;
  }

  if (error_blobs_) {
    status = ZX_ERR_BAD_STATE;
  }

  return status;
}

zx_status_t BlobfsChecker::Check() {
  TraverseInodeBitmap();
  TraverseBlockBitmap();
  return CheckAllocatedCounts();
}

BlobfsChecker::BlobfsChecker(std::unique_ptr<Blobfs> blobfs)
    : blobfs_(std::move(blobfs)),
      alloc_inodes_(0),
      alloc_blocks_(0),
      error_blobs_(0),
      inode_blocks_(0) {}

zx_status_t BlobfsChecker::Initialize(bool apply_journal) {
#ifdef __Fuchsia__
  zx_status_t status;
  if (apply_journal) {
    status = fs::ReplayJournal(blobfs_.get(), blobfs_.get(), JournalStartBlock(blobfs_->info_),
                               JournalBlocks(blobfs_->info_), kBlobfsBlockSize, nullptr);
    if (status != ZX_OK) {
      FS_TRACE_ERROR("blobfs: Unable to apply journal contents: %d\n", status);
      return status;
    }
  }

  status = CheckFvmConsistency(&blobfs_->Info(), blobfs_->Device());
  if (status != ZX_OK) {
    FS_TRACE_ERROR("blobfs: Inconsistent metadata does not match FVM: %d\n", status);
    return status;
  }
#endif
  return ZX_OK;
}

#ifdef __Fuchsia__
zx_status_t CheckFvmConsistency(const Superblock* info, BlockDevice* device) {
  if ((info->flags & kBlobFlagFVM) == 0) {
    return ZX_OK;
  }

  fuchsia_hardware_block_volume_VolumeInfo fvm_info;
  zx_status_t status = device->VolumeQuery(&fvm_info);
  if (status != ZX_OK) {
    FS_TRACE_ERROR("blobfs: Unable to query FVM, status: %s\n", zx_status_get_string(status));
    return status;
  }

  if (info->slice_size != fvm_info.slice_size) {
    FS_TRACE_ERROR("blobfs: Slice size did not match expected\n");
    return ZX_ERR_BAD_STATE;
  }
  const size_t kBlocksPerSlice = info->slice_size / kBlobfsBlockSize;

  size_t expected_count[4];
  expected_count[0] = info->abm_slices;
  expected_count[1] = info->ino_slices;
  expected_count[2] = info->journal_slices;
  expected_count[3] = info->dat_slices;

  uint64_t start_slices[4];
  start_slices[0] = kFVMBlockMapStart / kBlocksPerSlice;
  start_slices[1] = kFVMNodeMapStart / kBlocksPerSlice;
  start_slices[2] = kFVMJournalStart / kBlocksPerSlice;
  start_slices[3] = kFVMDataStart / kBlocksPerSlice;

  fuchsia_hardware_block_volume_VsliceRange
      ranges[fuchsia_hardware_block_volume_MAX_SLICE_REQUESTS];
  size_t actual_ranges_count;
  status = device->VolumeQuerySlices(start_slices, fbl::count_of(start_slices), ranges,
                                     &actual_ranges_count);
  if (status != ZX_OK) {
    FS_TRACE_ERROR("blobfs: Cannot query slices, status: %s\n", zx_status_get_string(status));
    return status;
  }

  if (actual_ranges_count != fbl::count_of(start_slices)) {
    FS_TRACE_ERROR("blobfs: Missing slice\n");
    return ZX_ERR_BAD_STATE;
  }

  for (size_t i = 0; i < fbl::count_of(start_slices); i++) {
    size_t blobfs_count = expected_count[i];
    size_t fvm_count = ranges[i].count;

    if (!ranges[i].allocated || fvm_count < blobfs_count) {
      // Currently, since Blobfs can only grow new slices, it should not be possible for
      // the FVM to report a slice size smaller than what is reported by Blobfs. In this
      // case, automatically fail without trying to resolve the situation, as it is
      // possible that Blobfs structures are allocated in the slices that have been lost.
      FS_TRACE_ERROR("blobfs: Mismatched slice count\n");
      return ZX_ERR_IO_DATA_INTEGRITY;
    }

    if (fvm_count > blobfs_count) {
      // If FVM reports more slices than we expect, try to free remainder.
      uint64_t offset = start_slices[i] + blobfs_count;
      uint64_t length = fvm_count - blobfs_count;
      zx_status_t status = device->VolumeShrink(offset, length);
      if (status != ZX_OK) {
        FS_TRACE_ERROR("blobfs: Unable to shrink to expected size: %s\n",
                       zx_status_get_string(status));
        return status;
      }
    }
  }

  return ZX_OK;
}
#endif  // ifdef __Fuchsia__

}  // namespace blobfs
