// 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 <string.h>

#include <safemath/checked_math.h>

#include "src/storage/f2fs/f2fs.h"

namespace f2fs {

void F2fs::PutSuper() {
#if 0  // porting needed
  // DestroyStats(superblock_info_.get());
  // StopGcThread(superblock_info_.get());
#endif

  WriteCheckpoint(false, true);
  if (superblock_info_->TestCpFlags(CpFlag::kCpErrorFlag)) {
    // In the checkpoint error case, flush the dirty vnode list.
    GetVCache().ForDirtyVnodesIf([&](fbl::RefPtr<VnodeF2fs> &vnode) {
      GetVCache().RemoveDirty(vnode.get());
      return ZX_OK;
    });
  }
  writer_.reset();
  ResetPsuedoVnodes();
  GetVCache().Reset();

#ifdef __Fuchsia__
  GetDirEntryCache().Reset();
#endif  // __Fuchsia__

  node_manager_->DestroyNodeManager();
  segment_manager_->DestroySegmentManager();

  node_manager_.reset();
  segment_manager_.reset();
  raw_sb_.reset();
  superblock_info_.reset();
}

void F2fs::SyncFs(bool bShutdown) {
  // TODO:: Consider !superblock_info_.IsDirty()
  if (bShutdown) {
    FX_LOGS(INFO) << "[f2fs] Unmount triggered";
    WritebackOperation op;
    // Checkpointing will flush all Pages that Writer is holding.
    op.if_vnode = [](fbl::RefPtr<VnodeF2fs> &vnode) {
      if (!vnode->IsDir()) {
        return ZX_OK;
      }
      return ZX_ERR_NEXT;
    };
    SyncDirtyDataPages(op);
  } else {
    WriteCheckpoint(false, false);
  }
}

#if 0  // porting needed
// int F2fs::F2fsStatfs(dentry *dentry /*, kstatfs *buf*/) {
  // super_block *sb = dentry->d_sb;
  // SuperblockInfo *superblock_info = F2FS_SB(sb);
  // u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
  // block_t total_count, user_block_count, start_count, ovp_count;

  // total_count = LeToCpu(superblock_info->raw_super->block_count);
  // user_block_count = superblock_info->GetUserBlockCount();
  // start_count = LeToCpu(superblock_info->raw_super->segment0_blkaddr);
  // ovp_count = GetSmInfo(superblock_info).ovp_segments << superblock_info->GetLogBlocksPerSeg();
  // buf->f_type = kF2fsSuperMagic;
  // buf->f_bsize = superblock_info->GetBlocksize();

  // buf->f_blocks = total_count - start_count;
  // buf->f_bfree = buf->f_blocks - ValidUserBlocks(superblock_info) - ovp_count;
  // buf->f_bavail = user_block_count - ValidUserBlocks(superblock_info);

  // buf->f_files = ValidInodeCount(superblock_info);
  // buf->f_ffree = superblock_info->GetTotalNodeCount() - ValidNodeCount(superblock_info);

  // buf->f_namelen = kMaxNameLen;
  // buf->f_fsid.val[0] = (u32)id;
  // buf->f_fsid.val[1] = (u32)(id >> 32);

  // return 0;
// }

// VnodeF2fs *F2fs::F2fsNfsGetInode(uint64_t ino, uint32_t generation) {
//   fbl::RefPtr<VnodeF2fs> vnode_refptr;
//   VnodeF2fs *vnode = nullptr;
//   int err;

//   if (ino < superblock_info_->GetRootIno())
//     return (VnodeF2fs *)ErrPtr(-ESTALE);

//   /*
//    * f2fs_iget isn't quite right if the inode is currently unallocated!
//    * However f2fs_iget currently does appropriate checks to handle stale
//    * inodes so everything is OK.
//    */
//   err = VnodeF2fs::Vget(this, ino, &vnode_refptr);
//   if (err)
//     return (VnodeF2fs *)ErrPtr(err);
//   vnode = vnode_refptr.get();
//   if (generation && vnode->i_generation != generation) {
//     /* we didn't find the right inode.. */
//     return (VnodeF2fs *)ErrPtr(-ESTALE);
//   }
//   return vnode;
// }

// struct fid {};

// dentry *F2fs::F2fsFhToDentry(fid *fid, int fh_len, int fh_type) {
//   return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
//             f2fs_nfs_get_inode);
// }

// dentry *F2fs::F2fsFhToParent(fid *fid, int fh_len, int fh_type) {
//   return generic_fh_to_parent(sb, fid, fh_len, fh_type,
//             f2fs_nfs_get_inode);
// }
#endif

void F2fs::ParseOptions() {
  for (uint32_t i = 0; i < kOptMaxNum; ++i) {
    uint32_t value;
    if (mount_options_.GetValue(i, &value) == ZX_OK) {
      switch (i) {
        case kOptActiveLogs:
          superblock_info_->SetActiveLogs(safemath::checked_cast<int>(value));
          break;
        case kOptDiscard:
          if (value)
            superblock_info_->SetOpt(kMountDiscard);
          break;
        case kOptBgGcOff:
          if (value)
            superblock_info_->SetOpt(kMountBgGcOff);
          break;
        case kOptNoHeap:
          if (value)
            superblock_info_->SetOpt(kMountNoheap);
          break;
        case kOptDisableExtIdentify:
          if (value)
            superblock_info_->SetOpt(kMountDisableExtIdentify);
          break;
        case kOptNoUserXAttr:
          if (value)
            superblock_info_->SetOpt(kMountNoXAttr);
          break;
        case kOptNoAcl:
          if (value)
            superblock_info_->SetOpt(kMountNoAcl);
          break;
        case kOptDisableRollForward:
          if (value)
            superblock_info_->SetOpt(kMountDisableRollForward);
          break;
        case kOptInlineXattr:
          if (value)
            superblock_info_->SetOpt(kMountInlineXattr);
          break;
        case kOptInlineData:
          if (value)
            superblock_info_->SetOpt(kMountInlineData);
          break;
        case kOptInlineDentry:
          if (value)
            superblock_info_->SetOpt(kMountInlineDentry);
          break;
        default:
          FX_LOGS(WARNING) << mount_options_.GetNameView(i) << " is not supported.";
          break;
      };
    }
  }
}

loff_t F2fs::MaxFileSize(unsigned bits) {
  loff_t result = kAddrsPerInode;
  loff_t leaf_count = kAddrsPerBlock;

  /* two direct node blocks */
  result += (leaf_count * 2);

  /* two indirect node blocks */
  leaf_count *= kNidsPerBlock;
  result += (leaf_count * 2);

  /* one double indirect node block */
  leaf_count *= kNidsPerBlock;
  result += leaf_count;

  result <<= bits;
  return result;
}

zx_status_t F2fs::SanityCheckRawSuper() {
  unsigned int blocksize;

  if (kF2fsSuperMagic != LeToCpu(raw_sb_->magic)) {
    return ZX_ERR_INVALID_ARGS;
  }

  // Currently, support 512/1024/2048/4096 block size
  blocksize = 1 << LeToCpu(raw_sb_->log_blocksize);
  if (blocksize != kPageSize)
    return ZX_ERR_INVALID_ARGS;
  if (LeToCpu(raw_sb_->log_sectorsize) > kMaxLogSectorSize ||
      LeToCpu(raw_sb_->log_sectorsize) < kMinLogSectorSize)
    return ZX_ERR_INVALID_ARGS;
  if ((LeToCpu(raw_sb_->log_sectors_per_block) + LeToCpu(raw_sb_->log_sectorsize)) !=
      kMaxLogSectorSize)
    return ZX_ERR_INVALID_ARGS;
  return ZX_OK;
}

zx_status_t F2fs::SanityCheckCkpt() {
  unsigned int total, fsmeta;

  total = LeToCpu(raw_sb_->segment_count);
  fsmeta = LeToCpu(raw_sb_->segment_count_ckpt);
  fsmeta += LeToCpu(raw_sb_->segment_count_sit);
  fsmeta += LeToCpu(raw_sb_->segment_count_nat);
  fsmeta += LeToCpu(superblock_info_->GetCheckpoint().rsvd_segment_count);
  fsmeta += LeToCpu(raw_sb_->segment_count_ssa);

  if (fsmeta >= total) {
    return ZX_ERR_BAD_STATE;
  }

  uint32_t sit_ver_bitmap_bytesize =
      ((LeToCpu(raw_sb_->segment_count_sit) / 2) << LeToCpu(raw_sb_->log_blocks_per_seg)) / 8;
  uint32_t nat_ver_bitmap_bytesize =
      ((LeToCpu(raw_sb_->segment_count_nat) / 2) << LeToCpu(raw_sb_->log_blocks_per_seg)) / 8;
  block_t nat_blocks = (LeToCpu(raw_sb_->segment_count_nat) >> 1)
                       << LeToCpu(raw_sb_->log_blocks_per_seg);

  if (superblock_info_->GetCheckpoint().sit_ver_bitmap_bytesize != sit_ver_bitmap_bytesize ||
      superblock_info_->GetCheckpoint().nat_ver_bitmap_bytesize != nat_ver_bitmap_bytesize ||
      superblock_info_->GetCheckpoint().next_free_nid >= kNatEntryPerBlock * nat_blocks) {
    return ZX_ERR_BAD_STATE;
  }

  return ZX_OK;
}

void F2fs::InitSuperblockInfo() {
  superblock_info_->SetLogSectorsPerBlock(LeToCpu(RawSb().log_sectors_per_block));
  superblock_info_->SetLogBlocksize(LeToCpu(RawSb().log_blocksize));
  superblock_info_->SetBlocksize(1 << superblock_info_->GetLogBlocksize());
  superblock_info_->SetLogBlocksPerSeg(LeToCpu(RawSb().log_blocks_per_seg));
  superblock_info_->SetBlocksPerSeg(1 << superblock_info_->GetLogBlocksPerSeg());
  superblock_info_->SetSegsPerSec(LeToCpu(RawSb().segs_per_sec));
  superblock_info_->SetSecsPerZone(LeToCpu(RawSb().secs_per_zone));
  superblock_info_->SetTotalSections(LeToCpu(RawSb().section_count));
  superblock_info_->SetTotalNodeCount((LeToCpu(RawSb().segment_count_nat) / 2) *
                                      superblock_info_->GetBlocksPerSeg() * kNatEntryPerBlock);
  superblock_info_->SetRootIno(LeToCpu(RawSb().root_ino));
  superblock_info_->SetNodeIno(LeToCpu(RawSb().node_ino));
  superblock_info_->SetMetaIno(LeToCpu(RawSb().meta_ino));

  std::vector<std::string> extension_list;
  for (int index = 0; index < safemath::checked_cast<int>(RawSb().extension_count); ++index) {
    ZX_ASSERT(index < kMaxExtension);
    ZX_ASSERT(RawSb().extension_list[index][7] == '\0');
    extension_list.push_back(reinterpret_cast<char *>(RawSb().extension_list[index]));
  }
  ZX_ASSERT(RawSb().extension_count == extension_list.size());
  superblock_info_->SetExtensionList(std::move(extension_list));
}

void F2fs::Reset() {
  if (root_vnode_) {
    root_vnode_.reset();
  }
  if (node_manager_) {
    node_manager_->DestroyNodeManager();
    node_manager_.reset();
  }
  if (segment_manager_) {
    segment_manager_->DestroySegmentManager();
    segment_manager_.reset();
  }
  if (superblock_info_) {
    superblock_info_.reset();
  }
}

zx_status_t F2fs::FillSuper() {
  zx_status_t err = ZX_OK;
  auto reset = fit::defer([&] { Reset(); });

  // allocate memory for f2fs-specific super block info
  superblock_info_ = std::make_unique<SuperblockInfo>();

  ParseOptions();

  // sanity checking of raw super
  if (err = SanityCheckRawSuper(); err != ZX_OK) {
    return err;
  }

  superblock_info_->SetRawSuperblock(raw_sb_);
  superblock_info_->ClearOnRecovery();
  InitSuperblockInfo();

  node_vnode_ = std::make_unique<VnodeF2fs>(this, GetSuperblockInfo().GetNodeIno());
  meta_vnode_ = std::make_unique<VnodeF2fs>(this, GetSuperblockInfo().GetMetaIno());
  writer_ = std::make_unique<Writer>(bc_.get());

  if (err = GetValidCheckpoint(); err != ZX_OK) {
    return err;
  }

  // sanity checking of checkpoint
  if (err = SanityCheckCkpt(); err != ZX_OK) {
    return err;
  }

  superblock_info_->SetTotalValidNodeCount(
      LeToCpu(superblock_info_->GetCheckpoint().valid_node_count));
  superblock_info_->SetTotalValidInodeCount(
      LeToCpu(superblock_info_->GetCheckpoint().valid_inode_count));
  superblock_info_->SetUserBlockCount(
      static_cast<block_t>(LeToCpu(superblock_info_->GetCheckpoint().user_block_count)));
  superblock_info_->SetTotalValidBlockCount(
      static_cast<block_t>(LeToCpu(superblock_info_->GetCheckpoint().valid_block_count)));
  superblock_info_->SetLastValidBlockCount(superblock_info_->GetTotalValidBlockCount());
  superblock_info_->SetAllocValidBlockCount(0);

  InitOrphanInfo();

  segment_manager_ = std::make_unique<SegmentManager>(this);
  node_manager_ = std::make_unique<NodeManager>(this);
  if (err = segment_manager_->BuildSegmentManager(); err != ZX_OK) {
    return err;
  }

  if (err = node_manager_->BuildNodeManager(); err != ZX_OK) {
    return err;
  }

  // TODO: Enable gc after impl dirty data cache
  // BuildGcManager(superblock_info);

  // if there are nt orphan nodes free them
  if (err = RecoverOrphanInodes(); err != ZX_OK) {
    return err;
  }

  // read root inode and dentry
  if (err = VnodeF2fs::Vget(this, superblock_info_->GetRootIno(), &root_vnode_); err != ZX_OK) {
    err = ZX_ERR_NO_MEMORY;
    return err;
  }

  // root vnode is corrupted
  if (!root_vnode_->IsDir() || !root_vnode_->GetBlocks() || !root_vnode_->GetSize()) {
    return err;
  }

  if (!superblock_info_->TestOpt(kMountDisableRollForward)) {
    RecoverFsyncData();
  }

  // After POR, we can run background GC thread
  // TODO: Enable wb thread first, and then impl gc thread
  // err = StartGcThread(superblock_info);
  // if (err)
  //   goto fail;
  reset.cancel();
  return err;
}

void SuperblockInfo::IncNrOrphans() { n_orphans_ = safemath::CheckAdd(n_orphans_, 1).ValueOrDie(); }

void SuperblockInfo::DecNrOrphans() { n_orphans_ = safemath::CheckSub(n_orphans_, 1).ValueOrDie(); }

}  // namespace f2fs
