ADDRS_PER_INODE and ADDRS_PER_BLOCK are macros of a function, and if the
compiler does not optimize the code (-O0 for example), they would be
called in every single loop, which could cause significant performance
drops in some cases.
This scenario has been found before, refer to:
Commit: 1bb669e ("fsck.f2fs: avoid unnecessary recalculation")
To avoid this performance drop as much as possible, I changed the
function to 'inline' definition, which could mitigate such cases in
the future.
Signed-off-by: Wu Bo <[email protected]>
---
v2: Only modify when the macro's return value is fixed in 'for' loops.
---
fsck/dump.c | 5 +++--
fsck/fsck.c | 12 ++++++++----
fsck/mount.c | 4 +++-
include/f2fs_fs.h | 12 +++++++++++-
lib/libf2fs.c | 11 -----------
5 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/fsck/dump.c b/fsck/dump.c
index f5c95de..a5f344b 100644
--- a/fsck/dump.c
+++ b/fsck/dump.c
@@ -495,7 +495,7 @@ static int dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
{
u32 i = 0;
u64 ofs = 0;
- u32 addr_per_block;
+ u32 addr_per_block, addr_per_inode;
u16 type = le16_to_cpu(node_blk->i.i_mode);
int ret = 0;
@@ -543,9 +543,10 @@ static int dump_inode_blk(struct f2fs_sb_info *sbi, u32
nid,
}
addr_per_block = ADDRS_PER_BLOCK(&node_blk->i);
+ addr_per_inode = ADDRS_PER_INODE(&node_blk->i);
/* check data blocks in inode */
- for (i = 0; i < ADDRS_PER_INODE(&node_blk->i); i++, ofs++)
+ for (i = 0; i < addr_per_inode; i++, ofs++)
dump_data_blk(sbi, ofs * F2FS_BLKSIZE, le32_to_cpu(
node_blk->i.i_addr[get_extra_isize(node_blk) + i]),
type);
diff --git a/fsck/fsck.c b/fsck/fsck.c
index db44f9d..1230d7b 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -1516,8 +1516,9 @@ int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct
f2fs_inode *inode,
bool compressed = i_flags & F2FS_COMPR_FL;
bool compr_rel = inode->i_inline & F2FS_COMPRESS_RELEASED;
u32 cluster_size = 1 << inode->i_log_cluster_size;
+ u32 addrs = ADDRS_PER_BLOCK(inode);
- for (idx = 0; idx < ADDRS_PER_BLOCK(inode); idx++, child->pgofs++) {
+ for (idx = 0; idx < addrs; idx++, child->pgofs++) {
block_t blkaddr = le32_to_cpu(node_blk->dn.addr[idx]);
check_extent_info(child, blkaddr, 0);
@@ -3173,7 +3174,7 @@ static void fsck_disconnect_file_dnode(struct
f2fs_sb_info *sbi,
{
struct f2fs_node *node;
struct node_info ni;
- u32 addr;
+ u32 addr, addr_per_block;
int i, err;
node = calloc(F2FS_BLKSIZE, 1);
@@ -3187,7 +3188,8 @@ static void fsck_disconnect_file_dnode(struct
f2fs_sb_info *sbi,
release_block_cnt(sbi, dealloc);
release_block(sbi, ni.blk_addr, dealloc);
- for (i = 0; i < ADDRS_PER_BLOCK(inode); i++) {
+ addr_per_block = ADDRS_PER_BLOCK(inode);
+ for (i = 0; i < addr_per_block; i++) {
addr = le32_to_cpu(node->dn.addr[i]);
if (!addr)
continue;
@@ -3302,8 +3304,10 @@ static void fsck_disconnect_file(struct f2fs_sb_info
*sbi, nid_t ino,
/* clear data counters */
if (!(node->i.i_inline & (F2FS_INLINE_DATA | F2FS_INLINE_DENTRY))) {
+ u32 addrs = ADDRS_PER_INODE(&node->i);
+
ofs = get_extra_isize(node);
- for (i = 0; i < ADDRS_PER_INODE(&node->i); i++) {
+ for (i = 0; i < addrs; i++) {
block_t addr = le32_to_cpu(node->i.i_addr[ofs + i]);
if (!addr)
continue;
diff --git a/fsck/mount.c b/fsck/mount.c
index 6f640a0..990f1e0 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -281,6 +281,7 @@ void print_inode_info(struct f2fs_sb_info *sbi,
u32 namelen = le32_to_cpu(inode->i_namelen);
int enc_name = file_enc_name(inode);
int ofs = get_extra_isize(node);
+ u32 addrs;
pretty_print_filename(inode->i_name, namelen, en, enc_name);
if (name && en[0]) {
@@ -350,7 +351,8 @@ void print_inode_info(struct f2fs_sb_info *sbi,
}
}
- for (i = 0; i < ADDRS_PER_INODE(inode); i++) {
+ addrs = ADDRS_PER_INODE(inode);
+ for (i = 0; i < addrs; i++) {
block_t blkaddr;
char *flag = "";
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index 3095b59..d0877b9 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -1660,7 +1660,6 @@ struct f2fs_configuration {
extern int utf8_to_utf16(char *, const char *, size_t, size_t);
extern int utf16_to_utf8(char *, const char *, size_t, size_t);
extern int log_base_2(uint32_t);
-extern unsigned int addrs_per_page(struct f2fs_inode *, bool);
extern u64 f2fs_max_file_offset(struct f2fs_inode *);
extern __u32 f2fs_inode_chksum(struct f2fs_node *);
extern __u32 f2fs_checkpoint_chksum(struct f2fs_checkpoint *);
@@ -2212,4 +2211,15 @@ static inline bool __time_to_inject(int type, const char
*func,
return false;
}
+static inline unsigned int addrs_per_page(struct f2fs_inode *i, bool is_inode)
+{
+ unsigned int addrs = is_inode ? CUR_ADDRS_PER_INODE(i) -
+ get_inline_xattr_addrs(i) : DEF_ADDRS_PER_BLOCK;
+
+ if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
+ !(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
+ return addrs;
+ return ALIGN_DOWN(addrs, 1 << i->i_log_cluster_size);
+}
+
#endif /*__F2FS_FS_H */
diff --git a/lib/libf2fs.c b/lib/libf2fs.c
index 1a496b7..13e4d0d 100644
--- a/lib/libf2fs.c
+++ b/lib/libf2fs.c
@@ -516,17 +516,6 @@ opaque_seq:
return __f2fs_dentry_hash(name, len);
}
-unsigned int addrs_per_page(struct f2fs_inode *i, bool is_inode)
-{
- unsigned int addrs = is_inode ? CUR_ADDRS_PER_INODE(i) -
- get_inline_xattr_addrs(i) : DEF_ADDRS_PER_BLOCK;
-
- if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
- !(le32_to_cpu(i->i_flags) & F2FS_COMPR_FL))
- return addrs;
- return ALIGN_DOWN(addrs, 1 << i->i_log_cluster_size);
-}
-
u64 f2fs_max_file_offset(struct f2fs_inode *i)
{
if (!LINUX_S_ISREG(le16_to_cpu(i->i_mode)) ||
--
2.47.3
_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel