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

namespace f2fs {

bool F2fs::SpaceForRollForward() {
  f2fs_sb_info &sbi = SbInfo();
  if (sbi.last_valid_block_count + sbi.alloc_valid_block_count > sbi.user_block_count)
    return false;
  return true;
}

fsync_inode_entry *F2fs::GetFsyncInode(list_node_t *head, nid_t ino) {
  list_node_t *this_node;
  fsync_inode_entry *entry;

  list_for_every(head, this_node) {
    entry = containerof(this_node, fsync_inode_entry, list);
    if (entry->vnode->Ino() == ino)
      return entry;
  }
  return nullptr;
}

zx_status_t F2fs::RecoverDentry(Page *ipage, VnodeF2fs *vnode) {
  f2fs_node *raw_node = static_cast<f2fs_node *>(PageAddress(ipage));
  f2fs_inode *raw_inode = &(raw_node->i);
  fbl::RefPtr<VnodeF2fs> dir_refptr;
  Dir *dir;
  f2fs_dir_entry *de;
  Page *page;
  zx_status_t err = ZX_OK;

  if (!Nodemgr().IsDentDnode(ipage))
    goto out;

  err = VnodeF2fs::Vget(this, LeToCpu(raw_inode->i_pino), &dir_refptr);
  if (err != ZX_OK) {
    goto out;
  }

  dir =  static_cast<Dir *>(dir_refptr.get());

#if 0  // porting needed
  // parent.d_inode = dir;
  // dent.d_parent = &parent;
  // dent.d_name.len = LeToCpu(raw_inode->i_namelen);
  // dent.d_name.name = raw_inode->i_name;
#endif

  de = dir->FindEntry(vnode->i_name_sp_, &page);
  if (de) {
#if 0  // porting needed
    // kunmap(page);
#endif
    F2fsPutPage(page, 0);
  } else {
    dir->AddLink(vnode->i_name_sp_, vnode);
  }
  Iput(dir);
out:
#if 0  // porting needed
  // kunmap(ipage);
#endif
  return err;
}

zx_status_t F2fs::RecoverInode(VnodeF2fs *vnode, Page *node_page) {
  void *kaddr = PageAddress(node_page);
  struct f2fs_node *raw_node = static_cast<f2fs_node *>(kaddr);
  struct f2fs_inode *raw_inode = &(raw_node->i);

  vnode->i_mode_ = LeToCpu(raw_inode->i_mode);
  vnode->i_size_ = LeToCpu(raw_inode->i_size);
  vnode->i_atime_.tv_sec = LeToCpu(raw_inode->i_mtime);
  vnode->i_ctime_.tv_sec = LeToCpu(raw_inode->i_ctime);
  vnode->i_mtime_.tv_sec = LeToCpu(raw_inode->i_mtime);
  vnode->i_atime_.tv_nsec = LeToCpu(raw_inode->i_mtime_nsec);
  vnode->i_ctime_.tv_nsec = LeToCpu(raw_inode->i_ctime_nsec);
  vnode->i_mtime_.tv_nsec = LeToCpu(raw_inode->i_mtime_nsec);

  return RecoverDentry(node_page, vnode);
}

zx_status_t F2fs::FindFsyncDnodes(list_node_t *head) {
  f2fs_sb_info &sbi = SbInfo();
  uint64_t cp_ver = LeToCpu(sbi.ckpt->checkpoint_ver);
  curseg_info *curseg;
  fbl::RefPtr<VnodeF2fs> vnode_refptr;
  Page *page;
  block_t blkaddr;
  f2fs_inode *ri;
  f2fs_node *rn;
  zx_status_t err = 0;

  /* get node pages in the current segment */
  curseg = SegMgr::CURSEG_I(&sbi, CURSEG_WARM_NODE);
  blkaddr = StartBlock(&sbi, curseg->segno) + curseg->next_blkoff;

  /* read node page */
  page = GrabCachePage(nullptr, F2FS_NODE_INO(sbi_), blkaddr);
  if (!page)
    return ZX_ERR_NO_MEMORY;
#if 0  // porting needed
  // lock_page(page);
#endif

  while (true) {
    fsync_inode_entry *entry;
    void *kaddr = PageAddress(page);
    rn = static_cast<f2fs_node *>(kaddr);

    if (VnodeF2fs::Readpage(this, page, blkaddr, kReadSync)) {
      goto out;
    }

#ifdef F2FS_BU_DEBUG
    std::cout << "F2fs::FindFsyncDnodes, blkaddr=" << blkaddr << ", ino=" << rn->footer.ino
              << ", nid=" << rn->footer.nid << ", flag=" << rn->footer.flag
              << ", cp_ver=" << rn->footer.cp_ver << ", next_blkaddr=" << rn->footer.next_blkaddr
              << std::endl;
#endif

    if (cp_ver != Nodemgr().CpverOfNode(page)) {
      goto out;
    }

    if (!Nodemgr().IsFsyncDnode(page)) {
      goto next;
    }

    entry = GetFsyncInode(head, Nodemgr().InoOfNode(page));
    if (entry) {
      entry->blkaddr = blkaddr;
      if (IS_INODE(page) && Nodemgr().IsDentDnode(page)) {
        SetInodeFlag(&entry->vnode->fi_, FI_INC_LINK);
      }
    } else {
      if (IS_INODE(page) && Nodemgr().IsDentDnode(page)) {
        if (Nodemgr().RecoverInodePage(page)) {
          err = ZX_ERR_NO_MEMORY;
          goto out;
        }
      }

      /* add this fsync inode to the list */
      // entry = kmem_cache_alloc(fsync_entry_slab, GFP_NOFS);
      entry = new fsync_inode_entry;
      if (!entry) {
        err = ZX_ERR_NO_MEMORY;
        goto out;
      }
      list_initialize(&entry->list);
      list_add_tail(&entry->list, head);
      // vnode_refptr.reset(entry->vnode);
      // err = VnodeF2fs::Vget(this, Nodemgr().InoOfNode(page), &vnode_refptr);
      rn = static_cast<f2fs_node *>(PageAddress(page));
      ri = &(rn->i);

      entry->vnode = vnode_refptr.get();
      if (entry->vnode == nullptr) {
        err = ZX_ERR_NO_MEMORY;
        goto out;
      }
      entry->blkaddr = blkaddr;
    }
    if (IS_INODE(page)) {
      err = RecoverInode(entry->vnode, page);
      if (err) {
        goto out;
      }
    }
  next:
    /* check next segment */
    blkaddr = NodeMgr::NextBlkaddrOfNode(page);
    ClearPageUptodate(page);
  }
out:
#if 0  // porting needed
  // unlock_page(page);
  //__free_pages(page, 0);
#endif
  delete page;
  return err;
}

void F2fs::DestroyFsyncDnodes(list_node_t *head) {
  list_node_t *this_node;
  fsync_inode_entry *entry;
  list_for_every(head, this_node) {
    entry = containerof(this_node, fsync_inode_entry, list);
    Iput(entry->vnode);
    list_delete(&entry->list);
#if 0  // porting needed
    // kmem_cache_free(fsync_entry_slab, entry);
#endif
    delete entry;
  }
}

void F2fs::CheckIndexInPrevNodes(block_t blkaddr) {
  f2fs_sb_info &sbi = SbInfo();
  seg_entry *sentry;
  uint32_t segno = GetSegNo(&sbi, blkaddr);
  uint16_t blkoff = GetSegOffFromSeg0(&sbi, blkaddr) & (sbi.blocks_per_seg - 1);
  f2fs_summary sum;
  nid_t ino;
  void *kaddr;
  fbl::RefPtr<VnodeF2fs> vnode_refptr;
  VnodeF2fs *vnode;
  Page *node_page = nullptr;
  block_t bidx;
  int i;
  zx_status_t err = 0;

  sentry = Segmgr().GetSegEntry(segno);
  if (!f2fs_test_bit(blkoff, reinterpret_cast<char *>(sentry->cur_valid_map)))
    return;

  /* Get the previous summary */
  for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) {
    curseg_info *curseg = Segmgr().CURSEG_I(&sbi, i);
    if (curseg->segno == segno) {
      sum = curseg->sum_blk->entries[blkoff];
      break;
    }
  }
  if (i > CURSEG_COLD_DATA) {
    Page *sum_page = Segmgr().GetSumPage(segno);
    f2fs_summary_block *sum_node;
    kaddr = PageAddress(sum_page);
    sum_node = static_cast<f2fs_summary_block *>(kaddr);
    sum = sum_node->entries[blkoff];
    F2fsPutPage(sum_page, 1);
  }

  /* Get the node page */
  err = Nodemgr().GetNodePage(LeToCpu(sum.nid), &node_page);
#ifdef F2FS_BU_DEBUG
  if (err) {
    std::cout << "F2fs::CheckIndexInPrevNodes, GetNodePage Error!!!" << std::endl;
    return;
  }
#endif
  bidx = StartBidxOfNode(Nodemgr().OfsOfNode(node_page)) + LeToCpu(sum.ofs_in_node);
  ino = Nodemgr().InoOfNode(node_page);
  F2fsPutPage(node_page, 1);

  /* Deallocate previous index in the node page */
#if 0  // porting needed
  // vnode = F2fsIgetNowait(ino);
#else
  VnodeF2fs::Vget(this, ino, &vnode_refptr);
  vnode = vnode_refptr.get();
#endif
  vnode->TruncateHole(bidx, bidx + 1);
  Iput(vnode);
}

void F2fs::DoRecoverData(VnodeF2fs *vnode, Page *page, block_t blkaddr) {
  uint32_t start, end;
  dnode_of_data dn;
  f2fs_summary sum;
  node_info ni;

  start = StartBidxOfNode(Nodemgr().OfsOfNode(page));
  if (IS_INODE(page)) {
    end = start + ADDRS_PER_INODE;
  } else {
    end = start + ADDRS_PER_BLOCK;
  }

  SetNewDnode(&dn, vnode, nullptr, nullptr, 0);
  if (Nodemgr().GetDnodeOfData(&dn, start, 0))
    return;

  WaitOnPageWriteback(dn.node_page);

  Nodemgr().GetNodeInfo(dn.nid, &ni);
  ZX_ASSERT(ni.ino == Nodemgr().InoOfNode(page));
  ZX_ASSERT(Nodemgr().OfsOfNode(dn.node_page) == Nodemgr().OfsOfNode(page));

  for (; start < end; start++) {
    block_t src, dest;

    src = datablock_addr(dn.node_page, dn.ofs_in_node);
    dest = datablock_addr(page, dn.ofs_in_node);

    if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR) {
      if (src == NULL_ADDR) {
        int err = vnode->ReserveNewBlock(&dn);
        /* We should not get -ENOSPC */
        ZX_ASSERT(!err);
      }

      /* Check the previous node page having this index */
      CheckIndexInPrevNodes(dest);

      Segmgr().SetSummary(&sum, dn.nid, dn.ofs_in_node, ni.version);

      /* write dummy data page */
      Segmgr().RecoverDataPage(nullptr, &sum, src, dest);
      vnode->UpdateExtentCache(dest, &dn);
    }
    dn.ofs_in_node++;
  }

  /* write node page in place */
  Segmgr().SetSummary(&sum, dn.nid, 0, 0);
  if (IS_INODE(dn.node_page))
    Nodemgr().SyncInodePage(&dn);

  Nodemgr().CopyNodeFooter(dn.node_page, page);
  Nodemgr().FillNodeFooter(dn.node_page, dn.nid, ni.ino, Nodemgr().OfsOfNode(page), false);
#if 0  // porting needed
  // set_page_dirty(dn.node_page, this);
#else
  FlushDirtyNodePage(this, dn.node_page);
#endif

  Nodemgr().RecoverNodePage(dn.node_page, &sum, &ni, blkaddr);
  F2fsPutDnode(&dn);
}

void F2fs::RecoverData(list_node_t *head, int type) {
  f2fs_sb_info &sbi = SbInfo();
  uint64_t cp_ver = LeToCpu(sbi.ckpt->checkpoint_ver);
  curseg_info *curseg;
  Page *page;
  block_t blkaddr;

  /* get node pages in the current segment */
  curseg = SegMgr::CURSEG_I(&sbi, type);
  blkaddr = NextFreeBlkAddr(&sbi, curseg);

  /* read node page */
  page = GrabCachePage(nullptr, F2FS_NODE_INO(sbi_), blkaddr);
  if (page == nullptr)
    return;
#if 0  // porting needed
  // lock_page(page);
#endif

  while (true) {
    fsync_inode_entry *entry;

    if (VnodeF2fs::Readpage(this, page, blkaddr, kReadSync))
      goto out;

    if (cp_ver != Nodemgr().CpverOfNode(page))
      goto out;

    entry = GetFsyncInode(head, Nodemgr().InoOfNode(page));
    if (!entry)
      goto next;

    DoRecoverData(entry->vnode, page, blkaddr);

    if (entry->blkaddr == blkaddr) {
      Iput(entry->vnode);
      list_delete(&entry->list);
#if 0  // porting needed
      // kmem_cache_free(fsync_entry_slab, entry);
#endif
      delete entry;
    }
  next:
    /* check next segment */
    blkaddr = NodeMgr::NextBlkaddrOfNode(page);
    ClearPageUptodate(page);
  }
out:
#if 0  // porting needed
  // unlock_page(page);
  //__free_pages(page, 0);
#endif
  F2fsPutPage(page, 1);

  Segmgr().AllocateNewSegments();
}

void F2fs::RecoverFsyncData() {
  f2fs_sb_info &sbi = SbInfo();
  list_node_t inode_list;

#if 0  // porting needed
  // fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
  // 		sizeof(fsync_inode_entry), NULL);
  // if (unlikely(!fsync_entry_slab))
  // 	return;
#endif

  list_initialize(&inode_list);

  /* step #1: find fsynced inode numbers */
  if (FindFsyncDnodes(&inode_list)) {
    goto out;
  }

  if (list_is_empty(&inode_list)) {
    goto out;
  }

  /* step #2: recover data */
  sbi.por_doing = 1;
  RecoverData(&inode_list, CURSEG_WARM_NODE);
  sbi.por_doing = 0;
  ZX_ASSERT(list_is_empty(&inode_list));
out:
  DestroyFsyncDnodes(&inode_list);
#if 0  // porting needed
  // kmem_cache_destroy(fsync_entry_slab);
#endif
  WriteCheckpoint(false, false);
}

}  // namespace f2fs
