// 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 F2FS_VNODE_H_
#define 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, kF2fsHashBits); }

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

  void Sync(SyncCallback closure) final;

  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_; }
  f2fs_inode Inode() const { return inode_; }

  zx_status_t GetAttributes(fs::VnodeAttributes *a) 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 F2fsVget(F2fs *fs, uint64_t ino, fbl::RefPtr<VnodeF2fs> *out);
  void UpdateInode(Page *node_page);
  zx_status_t F2fsWriteInode(struct WritebackControl *wbc);
#if 0  // porting needed
  // void F2fsTruncate();
#endif
  int TruncateDataBlocksRange(struct dnode_of_data *dn, int count);
  void TruncateDataBlocks(struct dnode_of_data *dn);
  void TruncatePartialDataPage(uint64_t from);
#if 0  // porting needed
  // int TruncateBlocks(uint64_t from);
#endif
  int TruncateHole(pgoff_t pg_start, pgoff_t pg_end);
#if 0  // porting needed
  // void F2fsEvictInode();
#endif

  void __SetDataBlkaddr(struct dnode_of_data *dn, block_t new_addr);
  int ReserveNewBlock(struct dnode_of_data *dn);

#if 0  // porting needed
  // static int CheckExtentCache(struct inode *inode, pgoff_t pgofs,
  //        struct buffer_head *bh_result);
#endif
  void UpdateExtentCache(block_t blk_addr, struct dnode_of_data *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 F2fsReadpage(F2fs *fs, Page *page, block_t blk_addr, int type);
#if 0  // porting needed
  // static int GetDataBlockRo(struct inode *inode, sector_t iblock,
  //      struct buffer_head *bh_result, int create);
  // static int F2fsReadDataPage(struct file *file, struct page *page);
  // static int F2fsReadDataPages(struct file *file,
  //       struct address_space *mapping,
  //       struct list_head *pages, unsigned nr_pages);
#endif
  zx_status_t DoWriteDataPage(Page *page);
  zx_status_t F2fsWriteDataPage(Page *page, struct WritebackControl *wbc);
#if 0  // porting needed
  // int F2fsWriteDataPages(/*struct address_space *mapping,*/
  //                        struct WritebackControl *wbc);
#endif
  zx_status_t F2fsWriteBegin(size_t pos, size_t len, Page **page);
#if 0  // porting needed
  // ssize_t F2fsDirectIO(/*int rw, struct kiocb *iocb,
  //   const struct iovec *iov, */
  //                      loff_t offset, uint64_t nr_segs);
  //   [[maybe_unused]] static void F2fsInvalidateDataPage(struct Page *page, uint64_t offset);
  //   [[maybe_unused]] static int F2fsReleaseDataPage(struct Page *page, gfp_t wait);
  // int F2fsSetDataPageDirty(Page *page);
#endif

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

  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;
  struct timespec i_atime;
  struct timespec i_mtime;
  struct timespec i_ctime;
  uint32_t i_generation;

  uint64_t i_state;

  fbl::StringPiece i_name_sp;

  struct f2fs_inode_info fi;

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

void MarkInodeDirty(VnodeF2fs *vnode);

}  // namespace f2fs

#endif  // F2FS_VNODE_H_
