summaryrefslogtreecommitdiff
path: root/fs/f2fs/node.h
diff options
context:
space:
mode:
Diffstat (limited to 'fs/f2fs/node.h')
-rw-r--r--fs/f2fs/node.h191
1 files changed, 107 insertions, 84 deletions
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
index 5e114f352099..2704a5c6a54d 100644
--- a/fs/f2fs/node.h
+++ b/fs/f2fs/node.h
@@ -6,19 +6,26 @@
* http://www.samsung.com/
*/
/* start node id of a node block dedicated to the given node id */
-#define START_NID(nid) (((nid) / NAT_ENTRY_PER_BLOCK) * NAT_ENTRY_PER_BLOCK)
+static inline nid_t f2fs_start_nid(struct f2fs_sb_info *sbi, nid_t nid)
+{
+ unsigned int entries = NAT_ENTRY_PER_BLOCK(sbi);
+
+ return (nid / entries) * entries;
+}
/* node block offset on the NAT area dedicated to the given start node id */
-#define NAT_BLOCK_OFFSET(start_nid) ((start_nid) / NAT_ENTRY_PER_BLOCK)
+#define NAT_BLOCK_OFFSET(sbi, start_nid) \
+ ((start_nid) / NAT_ENTRY_PER_BLOCK(sbi))
-/* # of pages to perform synchronous readahead before building free nids */
-#define FREE_NID_PAGES 8
-#define MAX_FREE_NIDS (NAT_ENTRY_PER_BLOCK * FREE_NID_PAGES)
+/* # of blocks to perform synchronous readahead before building free nids */
+#define FREE_NID_BLOCKS 8
+#define MAX_FREE_NIDS(sbi) ((unsigned long)NAT_ENTRY_PER_BLOCK(sbi) * \
+ FREE_NID_BLOCKS)
/* size of free nid batch when shrinking */
#define SHRINK_NID_BATCH_SIZE 8
-#define DEF_RA_NID_PAGES 0 /* # of nid pages to be readaheaded */
+#define DEF_RA_NID_BLOCKS 0 /* # of nid blocks to be readaheaded */
/* maximum readahead size for node during getting data blocks */
#define MAX_RA_NODE 128
@@ -37,8 +44,8 @@
/* vector size for gang look-up from nat cache that consists of radix tree */
#define NAT_VEC_SIZE 32
-/* return value for read_node_page */
-#define LOCKED_PAGE 1
+/* return value for read_node_cache */
+#define LOCKED_CACHE 1
/* check pinned file's alignment status of physical blocks */
#define FILE_NOT_ALIGNED 1
@@ -150,7 +157,7 @@ enum mem_type {
READ_EXTENT_CACHE, /* indicates read extent cache */
AGE_EXTENT_CACHE, /* indicates age extent cache */
DISCARD_CACHE, /* indicates memory of cached discard cmds */
- COMPRESS_PAGE, /* indicates memory of cached compressed pages */
+ COMPRESS_BLOCK, /* indicates memory of cached compressed blocks */
BASE_CHECK, /* check kernel status */
};
@@ -208,7 +215,7 @@ static inline pgoff_t current_nat_addr(struct f2fs_sb_info *sbi, nid_t start)
* OLD = (segment_off * 512) * 2 + off_in_segment
* NEW = 2 * (segment_off * 512 + off_in_segment) - off_in_segment
*/
- block_off = NAT_BLOCK_OFFSET(start);
+ block_off = NAT_BLOCK_OFFSET(sbi, start);
block_addr = (pgoff_t)(nm_i->nat_blkaddr +
(block_off << 1) -
@@ -230,9 +237,10 @@ static inline pgoff_t next_nat_addr(struct f2fs_sb_info *sbi,
return block_addr + nm_i->nat_blkaddr;
}
-static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid)
+static inline void set_to_next_nat(struct f2fs_sb_info *sbi,
+ struct f2fs_nm_info *nm_i, nid_t start_nid)
{
- unsigned int block_off = NAT_BLOCK_OFFSET(start_nid);
+ unsigned int block_off = NAT_BLOCK_OFFSET(sbi, start_nid);
f2fs_change_bit(block_off, nm_i->nat_bitmap);
#ifdef CONFIG_F2FS_CHECK_FS
@@ -240,90 +248,95 @@ static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid)
#endif
}
-static inline nid_t ino_of_node(const struct folio *node_folio)
+static inline nid_t ino_of_node(struct f2fs_sb_info *sbi,
+ const struct f2fs_cached_block *entry)
{
- struct f2fs_node *rn = F2FS_NODE(node_folio);
- return le32_to_cpu(rn->footer.ino);
+ return le32_to_cpu(F2FS_NODE_FOOTER(sbi, entry)->ino);
}
-static inline nid_t nid_of_node(const struct folio *node_folio)
+static inline nid_t nid_of_node(struct f2fs_sb_info *sbi,
+ const struct f2fs_cached_block *entry)
{
- struct f2fs_node *rn = F2FS_NODE(node_folio);
- return le32_to_cpu(rn->footer.nid);
+ return le32_to_cpu(F2FS_NODE_FOOTER(sbi, entry)->nid);
}
-static inline unsigned int ofs_of_node(const struct folio *node_folio)
+static inline unsigned int ofs_of_node(struct f2fs_sb_info *sbi,
+ const struct f2fs_cached_block *entry)
{
- struct f2fs_node *rn = F2FS_NODE(node_folio);
- unsigned flag = le32_to_cpu(rn->footer.flag);
+ unsigned int flag = le32_to_cpu(F2FS_NODE_FOOTER(sbi, entry)->flag);
return flag >> OFFSET_BIT_SHIFT;
}
-static inline __u64 cpver_of_node(const struct folio *node_folio)
+static inline __u64 cpver_of_node(struct f2fs_sb_info *sbi,
+ const struct f2fs_cached_block *entry)
{
- struct f2fs_node *rn = F2FS_NODE(node_folio);
- return le64_to_cpu(rn->footer.cp_ver);
+ return le64_to_cpu(F2FS_NODE_FOOTER(sbi, entry)->cp_ver);
}
-static inline block_t next_blkaddr_of_node(const struct folio *node_folio)
+static inline block_t next_blkaddr_of_node(struct f2fs_sb_info *sbi,
+ const struct f2fs_cached_block *entry)
{
- struct f2fs_node *rn = F2FS_NODE(node_folio);
- return le32_to_cpu(rn->footer.next_blkaddr);
+ return le32_to_cpu(F2FS_NODE_FOOTER(sbi, entry)->next_blkaddr);
}
-static inline void fill_node_footer(const struct folio *folio, nid_t nid,
+static inline void fill_node_footer(struct f2fs_sb_info *sbi,
+ struct f2fs_cached_block *entry, nid_t nid,
nid_t ino, unsigned int ofs, bool reset)
{
- struct f2fs_node *rn = F2FS_NODE(folio);
+ struct f2fs_node *rn = CACHED_NODE(entry);
+ struct node_footer *footer = F2FS_NODE_FOOTER(sbi, entry);
unsigned int old_flag = 0;
if (reset)
- memset(rn, 0, sizeof(*rn));
+ memset(rn, 0, F2FS_BLKSIZE(sbi));
else
- old_flag = le32_to_cpu(rn->footer.flag);
+ old_flag = le32_to_cpu(footer->flag);
- rn->footer.nid = cpu_to_le32(nid);
- rn->footer.ino = cpu_to_le32(ino);
+ memset(footer, 0, sizeof(*footer));
+ footer->nid = cpu_to_le32(nid);
+ footer->ino = cpu_to_le32(ino);
/* should remain old flag bits such as COLD_BIT_SHIFT */
- rn->footer.flag = cpu_to_le32((ofs << OFFSET_BIT_SHIFT) |
+ footer->flag = cpu_to_le32((ofs << OFFSET_BIT_SHIFT) |
(old_flag & OFFSET_BIT_MASK));
}
-static inline void copy_node_footer(const struct folio *dst,
- const struct folio *src)
+static inline void copy_node_footer(struct f2fs_sb_info *sbi,
+ struct f2fs_cached_block *dst,
+ const struct f2fs_cached_block *src)
{
- struct f2fs_node *src_rn = F2FS_NODE(src);
- struct f2fs_node *dst_rn = F2FS_NODE(dst);
- memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer));
+ memcpy(F2FS_NODE_FOOTER(sbi, dst), F2FS_NODE_FOOTER(sbi, src),
+ sizeof(struct node_footer));
}
-static inline void fill_node_footer_blkaddr(struct folio *folio, block_t blkaddr)
+static inline void fill_node_footer_blkaddr(struct f2fs_sb_info *sbi,
+ struct f2fs_cached_block *entry, block_t blkaddr)
{
- struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_F_SB(folio));
- struct f2fs_node *rn = F2FS_NODE(folio);
+ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
+ struct node_footer *footer = F2FS_NODE_FOOTER(sbi, entry);
__u64 cp_ver = cur_cp_version(ckpt);
if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG))
cp_ver |= (cur_cp_crc(ckpt) << 32);
- rn->footer.cp_ver = cpu_to_le64(cp_ver);
- rn->footer.next_blkaddr = cpu_to_le32(blkaddr);
+ footer->cp_ver = cpu_to_le64(cp_ver);
+ footer->next_blkaddr = cpu_to_le32(blkaddr);
}
-static inline bool is_recoverable_dnode(const struct folio *folio)
+static inline bool is_recoverable_dnode(struct f2fs_sb_info *sbi,
+ const struct f2fs_cached_block *entry)
{
- struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_F_SB(folio));
+ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
__u64 cp_ver = cur_cp_version(ckpt);
/* Don't care crc part, if fsck.f2fs sets it. */
if (__is_set_ckpt_flags(ckpt, CP_NOCRC_RECOVERY_FLAG))
- return (cp_ver << 32) == (cpver_of_node(folio) << 32);
+ return (cp_ver << 32) == (cpver_of_node(sbi, entry) << 32);
if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG))
cp_ver |= (cur_cp_crc(ckpt) << 32);
- return cp_ver == cpver_of_node(folio);
+ return cp_ver == cpver_of_node(sbi, entry);
}
/*
@@ -347,43 +360,50 @@ static inline bool is_recoverable_dnode(const struct folio *folio)
* `- indirect node ((6 + 2N) + (N - 1)(N + 1))
* `- direct node
*/
-static inline bool IS_DNODE(const struct folio *node_folio)
+static inline bool IS_DNODE(struct f2fs_sb_info *sbi,
+ const struct f2fs_cached_block *entry)
{
- unsigned int ofs = ofs_of_node(node_folio);
+ unsigned int ofs = ofs_of_node(sbi, entry);
if (f2fs_has_xattr_block(ofs))
return true;
- if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK ||
- ofs == 5 + 2 * NIDS_PER_BLOCK)
+ if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK(sbi) ||
+ ofs == 5 + 2 * NIDS_PER_BLOCK(sbi))
return false;
- if (ofs >= 6 + 2 * NIDS_PER_BLOCK) {
- ofs -= 6 + 2 * NIDS_PER_BLOCK;
- if (!((long int)ofs % (NIDS_PER_BLOCK + 1)))
+ if (ofs >= 6 + 2 * NIDS_PER_BLOCK(sbi)) {
+ ofs -= 6 + 2 * NIDS_PER_BLOCK(sbi);
+ if (!((long)ofs % (NIDS_PER_BLOCK(sbi) + 1)))
return false;
}
return true;
}
-static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i)
+static inline bool set_nid(struct f2fs_sb_info *sbi,
+ struct f2fs_cached_block *entry, int off, nid_t nid, bool i)
{
- struct f2fs_node *rn = F2FS_NODE(folio);
+ struct f2fs_node *rn = CACHED_NODE(entry);
+ __le32 *inode_nids = F2FS_INODE_NIDS(sbi, entry);
+ __le32 *addr = i ? &inode_nids[off - NODE_DIR1_BLOCK(sbi)] : &rn->in.nid[off];
- f2fs_folio_wait_writeback(folio, NODE, true, true);
+ f2fs_cache_wait_writeback(entry);
+ if (*addr == cpu_to_le32(nid))
+ return false;
- if (i)
- rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
- else
- rn->in.nid[off] = cpu_to_le32(nid);
- return folio_mark_dirty(folio);
+ *addr = cpu_to_le32(nid);
+ f2fs_mark_cache_dirty(entry);
+ return true;
}
-static inline nid_t get_nid(const struct folio *folio, int off, bool i)
+static inline nid_t get_nid(struct f2fs_sb_info *sbi,
+ const struct f2fs_cached_block *entry, int off, bool i)
{
- struct f2fs_node *rn = F2FS_NODE(folio);
+ struct f2fs_node *rn = CACHED_NODE(entry);
+ const __le32 *inode_nids = F2FS_INODE_NIDS(sbi, entry);
+ int nid_index = off - NODE_DIR1_BLOCK(sbi);
if (i)
- return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]);
+ return le32_to_cpu(inode_nids[nid_index]);
return le32_to_cpu(rn->in.nid[off]);
}
@@ -394,40 +414,43 @@ static inline nid_t get_nid(const struct folio *folio, int off, bool i)
* - Mark cold data pages in page cache
*/
-static inline int is_node(const struct folio *folio, int type)
+static inline int is_node(struct f2fs_sb_info *sbi,
+ const struct f2fs_cached_block *entry, int type)
{
- struct f2fs_node *rn = F2FS_NODE(folio);
- return le32_to_cpu(rn->footer.flag) & BIT(type);
+ return le32_to_cpu(F2FS_NODE_FOOTER(sbi, entry)->flag) & BIT(type);
}
-#define is_cold_node(folio) is_node(folio, COLD_BIT_SHIFT)
-#define is_fsync_dnode(folio) is_node(folio, FSYNC_BIT_SHIFT)
-#define is_dent_dnode(folio) is_node(folio, DENT_BIT_SHIFT)
+#define is_cold_node(sbi, entry) is_node(sbi, entry, COLD_BIT_SHIFT)
+#define is_fsync_dnode(sbi, entry) is_node(sbi, entry, FSYNC_BIT_SHIFT)
+#define is_dent_dnode(sbi, entry) is_node(sbi, entry, DENT_BIT_SHIFT)
-static inline void __set_mark(const struct folio *folio, bool mark, int type)
+static inline void __set_mark(struct f2fs_sb_info *sbi,
+ struct f2fs_cached_block *entry, bool mark, int type)
{
- struct f2fs_node *rn = F2FS_NODE(folio);
- unsigned int flag = le32_to_cpu(rn->footer.flag);
+ struct node_footer *footer = F2FS_NODE_FOOTER(sbi, entry);
+ unsigned int flag = le32_to_cpu(footer->flag);
if (mark)
flag |= BIT(type);
else
flag &= ~BIT(type);
- rn->footer.flag = cpu_to_le32(flag);
+ footer->flag = cpu_to_le32(flag);
}
-static inline void set_cold_node(const struct folio *folio, bool is_dir)
+static inline void set_cold_node(struct f2fs_sb_info *sbi,
+ struct f2fs_cached_block *entry, bool is_dir)
{
- __set_mark(folio, !is_dir, COLD_BIT_SHIFT);
+ __set_mark(sbi, entry, !is_dir, COLD_BIT_SHIFT);
}
-static inline void set_mark(struct folio *folio, bool mark, int type)
+static inline void set_mark(struct f2fs_sb_info *sbi,
+ struct f2fs_cached_block *entry, bool mark, int type)
{
- __set_mark(folio, mark, type);
-
+ __set_mark(sbi, entry, mark, type);
#ifdef CONFIG_F2FS_CHECK_FS
- f2fs_inode_chksum_set(F2FS_F_SB(folio), folio);
+ f2fs_inode_chksum_set(sbi, entry);
#endif
}
-#define set_dentry_mark(folio, mark) set_mark(folio, mark, DENT_BIT_SHIFT)
-#define set_fsync_mark(folio, mark) set_mark(folio, mark, FSYNC_BIT_SHIFT)
+
+#define set_dentry_mark(sbi, entry, mark) set_mark(sbi, entry, mark, DENT_BIT_SHIFT)
+#define set_fsync_mark(sbi, entry, mark) set_mark(sbi, entry, mark, FSYNC_BIT_SHIFT)