// 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"

namespace f2fs {

/**
 * We guarantee no failure on the returned page.
 */

Page *F2fs::GrabMetaPage(pgoff_t index) {
  Page *page;

  while (!(page = GrabCachePage(nullptr, MetaIno(sbi_.get()), index))) {
#if 0  // porting needed
    // cond_resched();
#endif
  }
  /* We wait writeback only inside grab_meta_page() */
  WaitOnPageWriteback(page);
  SetPageUptodate(page);
  return page;
}

Page *F2fs::GetMetaPage(pgoff_t index) {
  Page *page;
repeat:
  page = GrabCachePage(nullptr, MetaIno(sbi_.get()), index);
  if (!page) {
#if 0  // porting needed
    // cond_resched();
#endif
    goto repeat;
  }
  if (VnodeF2fs::Readpage(this, static_cast<Page *>(PageAddress(page)), index, kReadSync)) {
    F2fsPutPage(page, 1);
    goto repeat;
  }
#if 0  // porting needed
  // mark_page_accessed(page);
#endif

  /* We do not allow returning an errorneous page */
  return page;
}

zx_status_t F2fs::F2fsWriteMetaPage(Page *page, WritebackControl *wbc) {
  zx_status_t err;

  WaitOnPageWriteback(page);

  err = this->Segmgr().WriteMetaPage(page, wbc);
  if (err) {
#if 0  // porting needed
    // wbc->pages_skipped++;
    // set_page_dirty(page, this);
#else
    FlushDirtyMetaPage(this, page);
#endif
  }

  DecPageCount(&GetSbInfo(), CountType::kDirtyMeta);

  /* In this case, we should not unlock this page */
#if 0  // porting needed
  // if (err != kAopWritepageActivate)
  // unlock_page(page);
#endif
  return err;
}

#if 0  // porting needed
// int F2fs::F2fsWriteMetaPages(address_space *mapping, WritebackControl *wbc) {
//   struct block_device *bdev = sbi_->sb->s_bdev;
//   long written;

//   if (wbc->for_kupdate)
//   	return 0;

//   if (GetPages(sbi_, CountType::kDirtyMeta) == 0)
//   	return 0;

//   /* if mounting is failed, skip writing node pages */
//   mtx_lock(&sbi_->cp_mutex);
//   written = sync_meta_pages(sbi_.get(), META, bio_get_nr_vecs(bdev));
//   mtx_unlock(&sbi_->cp_mutex);
//   wbc->nr_to_write -= written;
//   return 0;
// }
#endif

int64_t F2fs::SyncMetaPages(PageType type, int64_t nr_to_write) {
#if 0  // porting needed
  // address_space *mapping = sbi->meta_inode->i_mapping;
  // pgoff_t index = 0, end = LONG_MAX;
  // pagevec pvec;
  // int64_t nwritten = 0;
  // struct WritebackControl wbc = {
  // 	.for_reclaim = 0,
  // };

  // pagevec_init(&pvec, 0);

  // while (index <= end) {
  // 	int i, nr_pages;
  // 	nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
  // 			PAGECACHE_TAG_DIRTY,
  // 			min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
  // 	if (nr_pages == 0)
  // 		break;

  // 	for (i = 0; i < nr_pages; i++) {
  // 		page *page = pvec.pages[i];
  // 		lock_page(page);
  // 		BUG_ON(page->mapping != mapping);
  // 		BUG_ON(!PageDirty(page));
  // 		ClearPageDirtyForIo(page);
  // 		f2fs_write_meta_page(page, &wbc);
  // 		if (nwritten++ >= nr_to_write)
  // 			break;
  // 	}
  // 	pagevec_release(&pvec);
  // 	cond_resched();
  // }

  // if (nwritten)
  // 	f2fs_submit_bio(sbi, type, nr_to_write == LONG_MAX);

  // return nwritten;
#else
  return 0;
#endif
}

#if 0  // porting needed
// int F2fs::F2fsSetMetaPageDirty(Page *page) {
//   SetPageUptodate(page);
//   if (!PageDirty(page)) {
//     // __set_page_dirty_nobuffers(page);
//     FlushDirtyMetaPage(this, page);
//     IncPageCount(&GetSbInfo(), CountType::kDirtyMeta);
//     SetSbDirt(&GetSbInfo());
//     return 1;
//   }
//   return 0;
// }
#endif

zx_status_t F2fs::CheckOrphanSpace() {
  SbInfo &sbi = GetSbInfo();
  uint32_t max_orphans;
  zx_status_t err = 0;

  /*
   * considering 512 blocks in a segment 5 blocks are needed for cp
   * and log segment summaries. Remaining blocks are used to keep
   * orphan entries with the limitation one reserved segment
   * for cp pack we can have max 1020*507 orphan entries
   */
  max_orphans = (sbi.blocks_per_seg - 5) * kOrphansPerBlock;
  mtx_lock(&sbi.orphan_inode_mutex);
  if (sbi.n_orphans >= max_orphans)
    err = ZX_ERR_NO_SPACE;
  mtx_unlock(&sbi.orphan_inode_mutex);
  return err;
}

void F2fs::AddOrphanInode(nid_t ino) {
  SbInfo &sbi = GetSbInfo();
  list_node_t *head, *this_node;
  OrphanInodeEntry *new_entry = nullptr, *orphan = nullptr;

  mtx_lock(&sbi.orphan_inode_mutex);
  head = &sbi.orphan_inode_list;
  list_for_every(head, this_node) {
    orphan = containerof(this_node, OrphanInodeEntry, list);
    if (orphan->ino == ino)
      goto out;
    if (orphan->ino > ino)
      break;
    orphan = nullptr;
  }
retry:
#if 0  // porting needed
  // new_entry = kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC);
#else
  new_entry = new OrphanInodeEntry;
#endif
  if (!new_entry) {
#if 0  // porting needed
    // cond_resched();
#endif
    goto retry;
  }
  new_entry->ino = ino;
  list_initialize(&new_entry->list);

  /* add new_oentry into list which is sorted by inode number */
  if (orphan) {
    OrphanInodeEntry *prev;

    /* get previous entry */
    prev = containerof(orphan->list.prev, OrphanInodeEntry, list);
    if (&prev->list != head) {
      /* insert new orphan inode entry */
      list_add(&prev->list, &new_entry->list);
    } else {
      list_add(head, &new_entry->list);
    }
  } else {
    list_add_tail(head, &new_entry->list);
  }
  sbi.n_orphans++;
out:
  mtx_unlock(&sbi.orphan_inode_mutex);
}

void F2fs::RemoveOrphanInode(nid_t ino) {
  SbInfo &sbi = GetSbInfo();
  list_node_t *this_node, *next, *head;
  OrphanInodeEntry *orphan;

  mtx_lock(&sbi.orphan_inode_mutex);
  head = &sbi.orphan_inode_list;
  list_for_every_safe(head, this_node, next) {
    orphan = containerof(this_node, OrphanInodeEntry, list);
    if (orphan->ino == ino) {
      list_delete(&orphan->list);
#if 0  // porting needed
      // kmem_cache_free(orphan_entry_slab, orphan);
#endif
      delete orphan;
      sbi.n_orphans--;
      break;
    }
  }
  mtx_unlock(&sbi.orphan_inode_mutex);
}

void F2fs::RecoverOrphanInode(nid_t ino) {
  fbl::RefPtr<VnodeF2fs> vnode;
  zx_status_t ret;
  ret = VnodeF2fs::Vget(this, ino, &vnode);
  ZX_ASSERT(ret == ZX_OK);
  vnode->ClearNlink();

  /* truncate all the data during Iput */
  Iput(vnode.get());
  vnode.reset();
}

int F2fs::RecoverOrphanInodes() {
  SbInfo &sbi = GetSbInfo();
  block_t start_blk, orphan_blkaddr, i, j;

  if (!(GetCheckpoint(&sbi)->ckpt_flags & kCpOrphanPresentFlag))
    return 0;

  sbi.por_doing = 1;
  start_blk = StartCpAddr(&sbi) + 1;
  orphan_blkaddr = StartSumAddr(&sbi) - 1;

  for (i = 0; i < orphan_blkaddr; i++) {
    Page *page = GetMetaPage(start_blk + i);
    OrphanBlock *orphan_blk;

    orphan_blk = static_cast<OrphanBlock *>(PageAddress(page));
    for (j = 0; j < LeToCpu(orphan_blk->entry_count); j++) {
      nid_t ino = LeToCpu(orphan_blk->ino[j]);
      RecoverOrphanInode(ino);
    }
    F2fsPutPage(page, 1);
  }
  /* clear Orphan Flag */
  GetCheckpoint(&sbi)->ckpt_flags &= (~kCpOrphanPresentFlag);
  sbi.por_doing = 0;
  return 0;
}

void F2fs::WriteOrphanInodes(block_t start_blk) {
  SbInfo &sbi = GetSbInfo();
  list_node_t *head, *this_node, *next;
  OrphanBlock *orphan_blk = nullptr;
  Page *page = nullptr;
  uint32_t nentries = 0;
  uint16_t index = 1;
  uint16_t orphan_blocks;

  orphan_blocks =
      static_cast<uint16_t>((sbi.n_orphans + (kOrphansPerBlock - 1)) / kOrphansPerBlock);

  mtx_lock(&sbi.orphan_inode_mutex);
  head = &sbi.orphan_inode_list;

  /* loop for each orphan inode entry and write them in Jornal block */
  list_for_every_safe(head, this_node, next) {
    OrphanInodeEntry *orphan;

    orphan = containerof(this_node, OrphanInodeEntry, list);

    if (nentries == kOrphansPerBlock) {
      /*
       * an orphan block is full of 1020 entries,
       * then we need to flush current orphan blocks
       * and bring another one in memory
       */
      orphan_blk->blk_addr = CpuToLe(index);
      orphan_blk->blk_count = CpuToLe(orphan_blocks);
      orphan_blk->entry_count = CpuToLe(nentries);
#if 0  // porting needed
      // set_page_dirty(page, this);
#else
      FlushDirtyMetaPage(this, page);
#endif
      F2fsPutPage(page, 1);
      index++;
      start_blk++;
      nentries = 0;
      page = nullptr;
    }
    if (page)
      goto page_exist;

    page = GrabMetaPage(start_blk);
    orphan_blk = static_cast<OrphanBlock *>(PageAddress(page));
    memset(orphan_blk, 0, sizeof(*orphan_blk));
  page_exist:
    orphan_blk->ino[nentries++] = CpuToLe(orphan->ino);
  }
  if (!page)
    goto end;

  orphan_blk->blk_addr = CpuToLe(index);
  orphan_blk->blk_count = CpuToLe(orphan_blocks);
  orphan_blk->entry_count = CpuToLe(nentries);
#if 0  // porting needed
  // set_page_dirty(page, this);
#else
  FlushDirtyMetaPage(this, page);
#endif
  F2fsPutPage(page, 1);
end:
  mtx_unlock(&sbi.orphan_inode_mutex);
}

Page *F2fs::ValidateCheckpoint(block_t cp_addr, uint64_t *version) {
  Page *cp_page_1, *cp_page_2;
  uint64_t blk_size = sbi_->blocksize;
  Checkpoint *cp_block;
  uint64_t cur_version = 0, pre_version = 0;
  uint32_t crc = 0;
  size_t crc_offset;

  /* Read the 1st cp block in this CP pack */
  cp_page_1 = GetMetaPage(cp_addr);

  /* get the version number */
  cp_block = static_cast<Checkpoint *>(PageAddress(cp_page_1));
  crc_offset = LeToCpu(cp_block->checksum_offset);
  if (crc_offset >= blk_size)
    goto invalid_cp1;

  crc = *reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(cp_block) + crc_offset);
  if (!F2fsCrcValid(crc, cp_block, crc_offset))
    goto invalid_cp1;

  pre_version = LeToCpu(cp_block->checkpoint_ver);

  /* Read the 2nd cp block in this CP pack */
  cp_addr += LeToCpu(cp_block->cp_pack_total_block_count) - 1;
  cp_page_2 = GetMetaPage(cp_addr);

  cp_block = static_cast<Checkpoint *>(PageAddress(cp_page_2));
  crc_offset = LeToCpu(cp_block->checksum_offset);
  if (crc_offset >= blk_size)
    goto invalid_cp2;

  crc = *reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(cp_block) + crc_offset);
  if (!F2fsCrcValid(crc, cp_block, crc_offset))
    goto invalid_cp2;

  cur_version = LeToCpu(cp_block->checkpoint_ver);

  if (cur_version == pre_version) {
    *version = cur_version;
    F2fsPutPage(cp_page_2, 1);
    return cp_page_1;
  }
invalid_cp2:
  F2fsPutPage(cp_page_2, 1);
invalid_cp1:
  F2fsPutPage(cp_page_1, 1);
  return nullptr;
}

zx_status_t F2fs::GetValidCheckpoint() {
  Checkpoint *cp_block;
  SuperBlock &fsb = RawSb();
  Page *cp1, *cp2, *cur_page;
  uint64_t blk_size = sbi_->blocksize;
  uint64_t cp1_version = 0, cp2_version = 0;
  uint64_t cp_start_blk_no;

  sbi_->ckpt = static_cast<Checkpoint *>(malloc(blk_size));
  if (!sbi_->ckpt)
    return -ENOMEM;
  /*
   * Finding out valid cp block involves read both
   * sets( cp pack1 and cp pack 2)
   */
  cp_start_blk_no = LeToCpu(fsb.cp_blkaddr);
  cp1 = ValidateCheckpoint(cp_start_blk_no, &cp1_version);

  /* The second checkpoint pack should start at the next segment */
  cp_start_blk_no += 1 << LeToCpu(fsb.log_blocks_per_seg);
  cp2 = ValidateCheckpoint(cp_start_blk_no, &cp2_version);

  if (cp1 && cp2) {
    if (VerAfter(cp2_version, cp1_version)) {
      cur_page = cp2;
    } else {
      cur_page = cp1;
    }
  } else if (cp1) {
    cur_page = cp1;
  } else if (cp2) {
    cur_page = cp2;
  } else {
    goto fail_no_cp;
  }

  cp_block = static_cast<Checkpoint *>(PageAddress(cur_page));
  memcpy(sbi_->ckpt, cp_block, blk_size);

#ifdef F2FS_BU_DEBUG
  int i;
  std::cout << std::endl << "F2fs::GetValidCheckpoint" << std::endl;
  for (i = 0; i < kMaxActiveNodeLogs; i++) {
    std::cout << "[" << i << "] cur_node_segno " << cp_block->cur_node_segno[i]
              << ", cur_node_blkoff=" << cp_block->cur_node_blkoff[i] << std::endl;
  }

  for (i = 0; i < kMaxActiveNodeLogs; i++) {
    std::cout << "[" << i << "] cur_data_segno " << cp_block->cur_data_segno[i]
              << ", cur_data_blkoff=" << cp_block->cur_data_blkoff[i] << std::endl;
  }
#endif

  F2fsPutPage(cp1, 1);
  F2fsPutPage(cp2, 1);
  return 0;

fail_no_cp:
  free(sbi_->ckpt);
  return -EINVAL;
}

#if 0  // porting needed
// void F2fs::SetDirtyDirPage(VnodeF2fs *vnode, Page *page) {
//   SbInfo &sbi = GetSbInfo();
//   list_node_t *head = &sbi.dir_inode_list;
//   DirInodeEntry *new_entry;
//   list_node_t *this_node;

//   if (!S_ISDIR(vnode->i_mode_))
//     return;
// retry:
//   // new = kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
//   new_entry = new DirInodeEntry;
//   if (!new_entry) {
//     // cond_resched();
//     goto retry;
//   }
//   new_entry->vnode = vnode;
//   list_initialize(&new_entry->list);

//   SpinLock(&sbi.dir_inode_lock);
//   list_for_every(head, this_node) {
//     DirInodeEntry *entry;
//     entry = containerof(this_node, DirInodeEntry, list);
//     if (entry->vnode == vnode) {
//       // kmem_cache_free(inode_entry_slab, new_entry);
//       delete new_entry;
//       goto out;
//     }
//   }
//   list_add_tail(&new_entry->list, head);
//   sbi.n_dirty_dirs++;

//   BUG_ON(!S_ISDIR(inode->i_mode));
// out:
//   IncPageCount(&sbi, CountType::kDirtyDents);
//   InodeIncDirtyDents(vnode);
//   // SetPagePrivate(page);

//   SpinUnlock(&sbi.dir_inode_lock);
// }

// void F2fs::RemoveDirtyDirInode(VnodeF2fs *vnode) {
//   SbInfo &sbi = GetSbInfo();
//   list_node_t *head = &sbi.dir_inode_list;
//   list_node_t *this_node;

//   if (!S_ISDIR(vnode->i_mode_))
//     return;

//   SpinLock(&sbi.dir_inode_lock);
//   // if (AtomicRead(&F2FS_I(vnode)->dirty_dents))
//   if (vnode->fi_.dirty_dents)
//     goto out;

//   list_for_every(head, this_node) {
//     DirInodeEntry *entry;
//     entry = containerof(this_node, DirInodeEntry, list);
//     if (entry->vnode == vnode) {
//       list_delete(&entry->list);
//       // kmem_cache_free(inode_entry_slab, entry);
//       delete entry;
//       sbi.n_dirty_dirs--;
//       break;
//     }
//   }
// out:
//   SpinUnlock(&sbi.dir_inode_lock);
// }
#endif

void F2fs::SyncDirtyDirInodes() {
  SbInfo &sbi = GetSbInfo();
  list_node_t *head = &sbi.dir_inode_list;
  DirInodeEntry *entry;
  fbl::RefPtr<VnodeF2fs> vnode;

retry:
  SpinLock(&sbi.dir_inode_lock);
  if (list_is_empty(head)) {
    SpinUnlock(&sbi.dir_inode_lock);
    return;
  }
  entry = containerof(head->next, DirInodeEntry, list);
  vnode.reset(static_cast<VnodeF2fs *>(Igrab(entry->vnode)));
  SpinUnlock(&sbi.dir_inode_lock);
  if (vnode) {
#if 0  // porting needed
    // filemap_flush(vnode->i_mapping);
#endif
    Iput(vnode.get());
    vnode.reset();
  } else {
    /*
     * We should submit bio, since it exists several
     * wribacking dentry pages in the freeing inode.
     */
    // TODO(unknown): bio[type] is empty
    // Segmgr().SubmitBio(DATA, true);
  }
  goto retry;
}

/**
 * Freeze all the FS-operations for checkpoint.
 */
void F2fs::BlockOperations() TA_NO_THREAD_SAFETY_ANALYSIS {
  SbInfo &sbi = GetSbInfo();
  int t;
  struct WritebackControl wbc = {
#if 0  // porting needed
      // .nr_to_write = LONG_MAX,
      // .sync_mode = WB_SYNC_ALL,

      // .for_reclaim = 0,
#endif
  };

  /* Stop renaming operation */
  mutex_lock_op(&sbi, LockType::kRename);
  mutex_lock_op(&sbi, LockType::kDentryOps);

retry_dents:
  /* write all the dirty dentry pages */
  SyncDirtyDirInodes();

  mutex_lock_op(&sbi, LockType::kDataWrtie);
  if (GetPages(&sbi, CountType::kDirtyDents)) {
    mutex_unlock_op(&sbi, LockType::kDataWrtie);
    goto retry_dents;
  }

  /* block all the operations */
  for (t = static_cast<int>(LockType::kDataNew); t <= static_cast<int>(LockType::kNodeTrunc); t++)
    mutex_lock_op(&sbi, static_cast<LockType>(t));

  mtx_lock(&sbi.write_inode);

  /*
   * POR: we should ensure that there is no dirty node pages
   * until finishing nat/sit flush.
   */
retry:
  Nodemgr().SyncNodePages(0, &wbc);

  mutex_lock_op(&sbi, LockType::kNodeWrite);

  if (GetPages(&sbi, CountType::kDirtyNodes)) {
    mutex_unlock_op(&sbi, LockType::kNodeWrite);
    goto retry;
  }
  mtx_unlock(&sbi.write_inode);
}

void F2fs::UnblockOperations() TA_NO_THREAD_SAFETY_ANALYSIS {
  SbInfo &sbi = GetSbInfo();
  int t;
  for (t = static_cast<int>(LockType::kNodeWrite); t >= static_cast<int>(LockType::kRename); t--)
    mutex_unlock_op(&sbi, static_cast<LockType>(t));
}

void F2fs::DoCheckpoint(bool is_umount) {
  SbInfo &sbi = GetSbInfo();
  Checkpoint *ckpt = GetCheckpoint(&sbi);
  nid_t last_nid = 0;
  block_t start_blk;
  Page *cp_page;
  uint32_t data_sum_blocks, orphan_blocks;
  void *kaddr;
  uint32_t crc32 = 0;
  int i;

  /* Flush all the NAT/SIT pages */
  while (GetPages(&sbi, CountType::kDirtyMeta))
    SyncMetaPages(PageType::kMeta, LONG_MAX);

  Nodemgr().NextFreeNid(&last_nid);

  /*
   * modify checkpoint
   * version number is already updated
   */
  ckpt->elapsed_time = CpuToLe(static_cast<uint64_t>(Segmgr().GetMtime()));
  ckpt->valid_block_count = CpuToLe(ValidUserBlocks(&sbi));
  ckpt->free_segment_count = CpuToLe(Segmgr().FreeSegments());
  for (i = 0; i < 3; i++) {
    ckpt->cur_node_segno[i] =
        CpuToLe(Segmgr().CursegSegno(i + static_cast<int>(CursegType::kCursegHotNode)));
    ckpt->cur_node_blkoff[i] =
        CpuToLe(Segmgr().CursegBlkoff(i + static_cast<int>(CursegType::kCursegHotNode)));
    ckpt->alloc_type[i + static_cast<int>(CursegType::kCursegHotNode)] =
        Segmgr().CursegAllocType(i + static_cast<int>(CursegType::kCursegHotNode));
  }
  for (i = 0; i < 3; i++) {
    ckpt->cur_data_segno[i] =
        CpuToLe(Segmgr().CursegSegno(i + static_cast<int>(CursegType::kCursegHotData)));
    ckpt->cur_data_blkoff[i] =
        CpuToLe(Segmgr().CursegBlkoff(i + static_cast<int>(CursegType::kCursegHotData)));
    ckpt->alloc_type[i + static_cast<int>(CursegType::kCursegHotData)] =
        Segmgr().CursegAllocType(i + static_cast<int>(CursegType::kCursegHotData));

#ifdef F2FS_BU_DEBUG
    std::cout << std::endl << "F2fs::DoCheckpoint " << std::endl;
    std::cout << "[" << i << "] cur_data_segno " << ckpt->cur_data_segno[i]
              << ", cur_data_blkoff=" << ckpt->cur_data_blkoff[i] << std::endl;

    std::cout << "[" << i << "] cur_node_segno " << ckpt->cur_node_segno[i]
              << ", cur_node_blkoff=" << ckpt->cur_node_blkoff[i] << std::endl;
#endif
  }

  ckpt->valid_node_count = CpuToLe(ValidNodeCount(&sbi));
  ckpt->valid_inode_count = CpuToLe(ValidInodeCount(&sbi));
  ckpt->next_free_nid = CpuToLe(last_nid);

  /* 2 cp  + n data seg summary + orphan inode blocks */
  data_sum_blocks = Segmgr().NpagesForSummaryFlush();
  if (data_sum_blocks < 3) {
    ckpt->ckpt_flags |= kCpCompactSumFlag;
  } else {
    ckpt->ckpt_flags &= (~kCpCompactSumFlag);
  }

  orphan_blocks = (sbi.n_orphans + kOrphansPerBlock - 1) / kOrphansPerBlock;
  ckpt->cp_pack_start_sum = 1 + orphan_blocks;
  ckpt->cp_pack_total_block_count = 2 + data_sum_blocks + orphan_blocks;

  if (is_umount) {
    ckpt->ckpt_flags |= kCpUmountFlag;
    ckpt->cp_pack_total_block_count += kNrCursegNodeType;
  } else {
    ckpt->ckpt_flags &= (~kCpUmountFlag);
  }

  if (sbi.n_orphans) {
    ckpt->ckpt_flags |= kCpOrphanPresentFlag;
  } else {
    ckpt->ckpt_flags &= (~kCpOrphanPresentFlag);
  }

  /* update SIT/NAT bitmap */
  Segmgr().GetSitBitmap(BitmapPrt(&sbi, MetaBitmap::kSitBitmap));
  Nodemgr().GetNatBitmap(BitmapPrt(&sbi, MetaBitmap::kNatBitmap));

  crc32 = F2fsCrc32(ckpt, LeToCpu(ckpt->checksum_offset));
  *reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(ckpt) +
                                LeToCpu(ckpt->checksum_offset)) = CpuToLe(crc32);

  start_blk = StartCpAddr(&sbi);

  /* write out checkpoint buffer at block 0 */
  cp_page = GrabMetaPage(start_blk++);
  kaddr = PageAddress(cp_page);
  memcpy(kaddr, ckpt, (1 << sbi.log_blocksize));
#if 0  // porting needed
  // set_page_dirty(cp_page, this);
#else
  FlushDirtyMetaPage(this, cp_page);
#endif
  F2fsPutPage(cp_page, 1);

  if (sbi.n_orphans) {
    WriteOrphanInodes(start_blk);
    start_blk += orphan_blocks;
  }

  Segmgr().WriteDataSummaries(start_blk);
  start_blk += data_sum_blocks;
  if (is_umount) {
    Segmgr().WriteNodeSummaries(start_blk);
    start_blk += kNrCursegNodeType;
  }

  /* writeout checkpoint block */
  cp_page = GrabMetaPage(start_blk);
  kaddr = PageAddress(cp_page);
  memcpy(kaddr, ckpt, (1 << sbi.log_blocksize));
#if 0  // porting needed
  // set_page_dirty(cp_page, this);
#else
  FlushDirtyMetaPage(this, cp_page);
#endif
  F2fsPutPage(cp_page, 1);

  /* wait for previous submitted node/meta pages writeback */
#if 0  // porting needed
  // while (GetPages(&sbi, kWriteback))
  //	congestion_wait(BLK_RW_ASYNC, HZ / 50);

  // filemap_fdatawait_range(sbi.node_inode->i_mapping, 0, LONG_MAX);
  // filemap_fdatawait_range(sbi.meta_inode->i_mapping, 0, LONG_MAX);
#endif

  /* update user_block_counts */
  sbi.last_valid_block_count = sbi.total_valid_block_count;
  sbi.alloc_valid_block_count = 0;

  /* Here, we only have one bio having CP pack */
#if 0  // porting needed
  // if (sbi.ckpt->ckpt_flags & kCpErrorFlag)
  //	sbi->sb->s_flags |= MS_RDONLY;
  // else
#endif
  SyncMetaPages(PageType::kMetaFlush, LONG_MAX);

  Segmgr().ClearPrefreeSegments();
  ResetSbDirt(&sbi);
}

/**
 * We guarantee that this checkpoint procedure should not fail.
 */
void F2fs::WriteCheckpoint(bool blocked, bool is_umount) {
  SbInfo &sbi = GetSbInfo();
  Checkpoint *ckpt = GetCheckpoint(&sbi);
  uint64_t ckpt_ver;

  // TODO(unknown): Need to confirm if blocked is true
  // if (!blocked) {
  mtx_lock(&sbi.cp_mutex);
  BlockOperations();
  //}

#if 0  // porting needed (bio[type] is empty)
  // Segmgr().SubmitBio(PageType::kData, true);
  // Segmgr().SubmitBio(PageType::kNode, true);
  // Segmgr().SubmitBio(PageType::kMeta, true);
#endif

  /*
   * update checkpoint pack index
   * Increase the version number so that
   * SIT entries and seg summaries are written at correct place
   */
  ckpt_ver = LeToCpu(ckpt->checkpoint_ver);
  ckpt->checkpoint_ver = CpuToLe(static_cast<uint64_t>(++ckpt_ver));

  /* write cached NAT/SIT entries to NAT/SIT area */
  Nodemgr().FlushNatEntries();
  Segmgr().FlushSitEntries();

  Segmgr().ResetVictimSegmap();

  /* unlock all the fs_lock[] in do_checkpoint() */
  DoCheckpoint(is_umount);

  UnblockOperations();
  mtx_unlock(&sbi.cp_mutex);
}

void F2fs::InitOrphanInfo() {
  SbInfo &sbi = GetSbInfo();
  mtx_init(&sbi.orphan_inode_mutex, mtx_plain);
  list_initialize(&sbi.orphan_inode_list);
  sbi.n_orphans = 0;
}

#if 0  // porting needed
// int F2fs::CreateCheckpointCaches() {
//   orphan_entry_slab = KmemCacheCreate("f2fs_orphan_entry",
//   		sizeof(OrphanInodeEntry), nullptr);
//   if (unlikely(!orphan_entry_slab))
//   	return -ENOMEM;
//   inode_entry_slab = KmemCacheCreate("f2fs_dirty_dir_entry",
//   		sizeof(DirInodeEntry), nullptr);
//   if (unlikely(!inode_entry_slab)) {
//   	kmem_cache_destroy(orphan_entry_slab);
//   	return -ENOMEM;
//   }
//   return 0;
// }

// void F2fs::DestroyCheckpointCaches(void) {
//   // kmem_cache_destroy(orphan_entry_slab);
//   // kmem_cache_destroy(inode_entry_slab);
// }
#endif

}  // namespace f2fs
