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

namespace f2fs {
void NodePage::FillNodeFooter(nid_t nid, nid_t ino, size_t ofs) {
  NodeFooter &raw_footer = node().footer;
  raw_footer.nid = CpuToLe(nid);
  raw_footer.ino = CpuToLe(ino);
  raw_footer.flag = CpuToLe(
      safemath::checked_cast<uint32_t>(ofs << static_cast<uint32_t>(BitShift::kOffsetBitShift)));
}

void NodePage::CopyNodeFooterFrom(NodePage &src) {
  memcpy(&node().footer, &src.node().footer, sizeof(NodeFooter));
}

void NodePage::FillNodeFooterBlkaddr(block_t blkaddr, uint64_t ver) {
  NodeFooter &raw_footer = node().footer;
  raw_footer.cp_ver = CpuToLe(ver);
  raw_footer.next_blkaddr = CpuToLe(blkaddr);
}

nid_t NodePage::InoOfNode() const { return LeToCpu(node().footer.ino); }

nid_t NodePage::NidOfNode() const { return LeToCpu(node().footer.nid); }

uint32_t NodePage::OfsOfNode() const {
  uint32_t flag = LeToCpu(node().footer.flag);
  return flag >> static_cast<int>(BitShift::kOffsetBitShift);
}

uint64_t NodePage::CpverOfNode() const { return LeToCpu(node().footer.cp_ver); }

block_t NodePage::NextBlkaddrOfNode() const { return LeToCpu(node().footer.next_blkaddr); }

// f2fs assigns the following node offsets described as (num).
// N = kNidsPerBlock
//
//  Inode block (0)
//    |- direct node (1)
//    |- direct node (2)
//    |- indirect node (3)
//    |            `- direct node (4 => 4 + N - 1)
//    |- indirect node (4 + N)
//    |            `- direct node (5 + N => 5 + 2N - 1)
//    `- double indirect node (5 + 2N)
//                 `- indirect node (6 + 2N)
//                       `- direct node (x(N + 1))
bool NodePage::IsDnode() const {
  uint32_t ofs = OfsOfNode();
  if (ofs == kOfsIndirectNode1 || ofs == kOfsIndirectNode2 || ofs == kOfsDoubleIndirectNode) {
    return false;
  }
  if (ofs >= kOfsDoubleIndirectNode + 1) {
    ofs -= kOfsDoubleIndirectNode + 1;
    if (ofs % (kNidsPerBlock + 1)) {
      return false;
    }
  }
  return true;
}

void NodePage::SetNid(size_t off, nid_t nid) {
  WaitOnWriteback();

  if (IsInode()) {
    node().i.i_nid[off - kNodeDir1Block] = CpuToLe(nid);
  } else {
    node().in.nid[off] = CpuToLe(nid);
  }
}

nid_t NodePage::GetNid(size_t off) const {
  if (IsInode()) {
    return LeToCpu(node().i.i_nid[off - kNodeDir1Block]);
  }
  return LeToCpu(node().in.nid[off]);
}

bool NodePage::IsColdNode() const {
  uint32_t flag = LeToCpu(node().footer.flag);
  uint32_t bit =
      safemath::CheckLsh(1U, static_cast<uint32_t>(BitShift::kColdBitShift)).ValueOrDie();
  return flag & bit;
}

bool NodePage::IsFsyncDnode() const {
  uint32_t flag = LeToCpu(node().footer.flag);
  uint32_t bit =
      safemath::CheckLsh(1U, static_cast<uint32_t>(BitShift::kFsyncBitShift)).ValueOrDie();
  return flag & bit;
}

bool NodePage::IsDentDnode() const {
  uint32_t flag = LeToCpu(node().footer.flag);
  uint32_t bit =
      safemath::CheckLsh(1U, static_cast<uint32_t>(BitShift::kDentBitShift)).ValueOrDie();
  return flag & bit;
}

void NodePage::SetColdNode(const bool is_dir) {
  Node &raw_node = node();
  uint32_t flag = LeToCpu(raw_node.footer.flag);
  uint32_t bit =
      safemath::CheckLsh(1U, static_cast<uint32_t>(BitShift::kColdBitShift)).ValueOrDie();
  if (is_dir) {
    flag &= ~bit;
  } else {
    flag |= bit;
  }
  raw_node.footer.flag = CpuToLe(flag);
}

void NodePage::SetFsyncMark(bool mark) {
  Node &raw_node = node();
  uint32_t flag = LeToCpu(raw_node.footer.flag);
  uint32_t bit =
      safemath::CheckLsh(1U, static_cast<uint32_t>(BitShift::kFsyncBitShift)).ValueOrDie();
  if (mark) {
    flag |= bit;
  } else {
    flag &= ~bit;
  }
  raw_node.footer.flag = CpuToLe(flag);
}

void NodePage::SetDentryMark(bool mark) {
  Node &raw_node = node();
  uint32_t flag = LeToCpu(raw_node.footer.flag);
  uint32_t bit =
      safemath::CheckLsh(1U, static_cast<uint32_t>(BitShift::kDentBitShift)).ValueOrDie();
  if (mark) {
    flag |= bit;
  } else {
    flag &= ~bit;
  }
  raw_node.footer.flag = CpuToLe(flag);
}

size_t NodePage::StartBidxOfNode(size_t num_addrs) const {
  size_t node_ofs = OfsOfNode(), NumOfIndirectNodes = 0;

  if (node_ofs == kOfsInode) {
    return 0;
  } else if (node_ofs <= kOfsDirectNode2) {
    NumOfIndirectNodes = 0;
  } else if (node_ofs >= kOfsIndirectNode1 && node_ofs < kOfsIndirectNode2) {
    NumOfIndirectNodes = 1;
  } else if (node_ofs >= kOfsIndirectNode2 && node_ofs < kOfsDoubleIndirectNode) {
    NumOfIndirectNodes = 2;
  } else {
    NumOfIndirectNodes = (node_ofs - kOfsDoubleIndirectNode - 2) / (kNidsPerBlock + 1);
  }

  size_t bidx = node_ofs - NumOfIndirectNodes - 1;
  return (num_addrs + safemath::CheckMul(bidx, kAddrsPerBlock)).ValueOrDie();
}

bool NodePage::IsInode() const {
  NodeFooter &raw_footer = node().footer;
  return raw_footer.nid == raw_footer.ino;
}

block_t *NodePage::addrs_array() const {
  Node &raw_node = node();
  if (IsInode()) {
    Inode &inode = raw_node.i;
    if (inode.i_inline & kExtraAttr) {
      return inode.i_addr + (inode.i_extra_isize / sizeof(uint32_t));
    }
    return inode.i_addr;
  }
  return raw_node.dn.addr;
}

block_t NodePage::GetBlockAddr(const size_t offset) const { return LeToCpu(addrs_array()[offset]); }

void NodePage::SetBlockAddr(const size_t offset, const block_t new_addr) const {
  addrs_array()[offset] = CpuToLe(new_addr);
}

void NodePage::SetDataBlkaddr(size_t ofs_in_node, block_t new_addr) {
  WaitOnWriteback();
  ZX_DEBUG_ASSERT(IsLocked());
  ZX_DEBUG_ASSERT((new_addr == kNewAddr && GetBlockAddr(ofs_in_node) == kNullAddr) ||
                  (new_addr != kNewAddr && GetBlockAddr(ofs_in_node) != kNullAddr));

  SetBlockAddr(ofs_in_node, new_addr);
  SetDirty();
}

}  // namespace f2fs
