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

#ifndef THIRD_PARTY_F2FS_VNODE_H_
#define THIRD_PARTY_F2FS_VNODE_H_

namespace f2fs {

// Used by fsck
class F2fs;

class VnodeF2fs : public fs::Vnode,
                  public fbl::SinglyLinkedListable<VnodeF2fs *>,
                  public fbl::Recyclable<VnodeF2fs> {
 public:
  explicit VnodeF2fs(F2fs *fs);
  explicit VnodeF2fs(F2fs *fs, ino_t ino);
  ~VnodeF2fs() = default;

  static void Allocate(F2fs *fs, ino_t ino, uint32_t mode, fbl::RefPtr<VnodeF2fs> *out);
  static void Create(F2fs *fs, ino_t ino, fbl::RefPtr<VnodeF2fs> *out);

  ino_t GetKey() const { return ino_; }

  static size_t GetHash(ino_t key) { return fnv1a_tiny(key, kHashBits); }

  using fs::Vnode::Open;
  zx_status_t Open(ValidatedOptions options, fbl::RefPtr<Vnode> *out_redirect);
  zx_status_t Close();

  void Sync(SyncCallback closure) final;
  zx_status_t SyncFile(loff_t start, loff_t end, int datasync);
  int NeedToSyncDir(SbInfo *sbi, VnodeF2fs *vnode);

  zx_status_t QueryFilesystem(fuchsia_io::wire::FilesystemInfo *info) final;

  void fbl_recycle() override;

  bool IsDirectory();

  F2fs *Vfs() const { return fs_; }
  ino_t Ino() const { return ino_; }
  Inode GetInode() const { return inode_; }

  zx_status_t GetAttributes(fs::VnodeAttributes *a) final;
  zx_status_t SetAttributes(fs::VnodeAttributesUpdate attr) final;

  zx_status_t GetNodeInfoForProtocol([[maybe_unused]] fs::VnodeProtocol protocol,
                                     [[maybe_unused]] fs::Rights rights,
                                     fs::VnodeRepresentation *info) final;

  fs::VnodeProtocolSet GetProtocols() const final;

#if 0  // porting needed
  // void F2fsSetInodeFlags();
  // int F2fsIgetTest(void *data);
  // VnodeF2fs *F2fsIgetNowait(uint64_t ino);
#endif

  static zx_status_t Vget(F2fs *fs, uint64_t ino, fbl::RefPtr<VnodeF2fs> *out);
  void UpdateInode(Page *node_page);
  zx_status_t WriteInode(WritebackControl *wbc);
  zx_status_t DoTruncate();
  int TruncateDataBlocksRange(DnodeOfData *dn, int count);
  void TruncateDataBlocks(DnodeOfData *dn);
  void TruncatePartialDataPage(uint64_t from);
  zx_status_t TruncateBlocks(uint64_t from);
  zx_status_t TruncateHole(pgoff_t pg_start, pgoff_t pg_end);
#if 0  // porting needed
  // void F2fsEvictInode();
#endif

  void SetDataBlkaddr(DnodeOfData *dn, block_t new_addr);
  int ReserveNewBlock(DnodeOfData *dn);

#if 0  // porting needed
  // static int CheckExtentCache(inode *inode, pgoff_t pgofs,
  //        buffer_head *bh_result);
#endif
  void UpdateExtentCache(block_t blk_addr, DnodeOfData *dn);
  zx_status_t FindDataPage(pgoff_t index, Page **out);
  zx_status_t GetLockDataPage(pgoff_t index, Page **out);
  zx_status_t GetNewDataPage(pgoff_t index, bool new_i_size, Page **out);

  static zx_status_t Readpage(F2fs *fs, Page *page, block_t blk_addr, int type);
#if 0  // porting needed
  // static int GetDataBlockRo(inode *inode, sector_t iblock,
  //      buffer_head *bh_result, int create);
  // static int F2fsReadDataPage(file *file, page *page);
  // static int F2fsReadDataPages(file *file,
  //       address_space *mapping,
  //       list_head *pages, unsigned nr_pages);
#endif
  zx_status_t DoWriteDataPage(Page *page);
  zx_status_t WriteDataPageReq(Page *page, WritebackControl *wbc);
#if 0  // porting needed
  // int F2fsWriteDataPages(/*address_space *mapping,*/
  //                        WritebackControl *wbc);
#endif
  zx_status_t WriteBegin(size_t pos, size_t len, Page **page);
#if 0  // porting needed
  // ssize_t F2fsDirectIO(/*int rw, kiocb *iocb,
  //   const iovec *iov, */
  //                      loff_t offset, uint64_t nr_segs);
  //   [[maybe_unused]] static void F2fsInvalidateDataPage(Page *page, uint64_t offset);
  //   [[maybe_unused]] static int F2fsReleaseDataPage(Page *page, gfp_t wait);
  // int F2fsSetDataPageDirty(Page *page);
#endif

  void IncNlink();
  void DropNlink();
  void ClearNlink();
  void SetNlink(uint32_t nlink);

  uint64_t GetBlocks();

  // TODO(unknown): non-public member variables
  fbl::Mutex v_lock_;
  mtx_t i_mutex_;

  umode_t i_mode_;
  uid_t i_uid_;
  gid_t i_gid_;
  unsigned int i_nlink_;

  uint64_t i_size_;
  blkcnt_t i_blocks_;
  timespec i_atime_;
  timespec i_mtime_;
  timespec i_ctime_;
  uint32_t i_generation_;

  uint64_t i_state_;

  std::string_view i_name_sp_;

  InodeInfo fi_;

 private:
  F2fs *fs_;
  ino_t ino_{};
  Inode inode_{};
  uint32_t fd_count_{};
};

void MarkInodeDirty(VnodeF2fs *vnode);

}  // namespace f2fs

#endif  // THIRD_PARTY_F2FS_VNODE_H_
