From 9e64efe2765a0a847cf949c83add17ac1e625f51 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Fri, 9 Aug 2019 18:52:57 +0800 Subject: [PATCH] f2fs-tools: introduce f2fs_ra_meta_pages() Introduce f2fs_ra_meta_pages() to readahead meta pages like we did in kernel. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fsck/f2fs.h | 28 +++++++++++++ fsck/fsck.c | 2 + fsck/fsck.h | 1 + fsck/mount.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++---- include/f2fs_fs.h | 5 +++ 5 files changed, 147 insertions(+), 8 deletions(-) diff --git a/fsck/f2fs.h b/fsck/f2fs.h index 6fc0bf3..52b81ff 100644 --- a/fsck/f2fs.h +++ b/fsck/f2fs.h @@ -37,6 +37,20 @@ struct list_head { struct list_head *next, *prev; }; +/* + * indicate meta/data type + */ +enum { + META_CP, + META_NAT, + META_SIT, + META_SSA, + META_MAX, + META_POR, +}; + +#define MAX_RA_BLOCKS 64 + enum { NAT_BITMAP, SIT_BITMAP @@ -329,6 +343,13 @@ static inline block_t __end_block_addr(struct f2fs_sb_info *sbi) ((t == CURSEG_HOT_NODE) || (t == CURSEG_COLD_NODE) || \ (t == CURSEG_WARM_NODE)) +#define MAIN_BLKADDR(sbi) \ + (SM_I(sbi) ? SM_I(sbi)->main_blkaddr : \ + le32_to_cpu(F2FS_RAW_SUPER(sbi)->main_blkaddr)) +#define SEG0_BLKADDR(sbi) \ + (SM_I(sbi) ? SM_I(sbi)->seg0_blkaddr : \ + le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment0_blkaddr)) + #define GET_SUM_BLKADDR(sbi, segno) \ ((sbi->sm_info->ssa_blkaddr) + segno) @@ -345,9 +366,16 @@ static inline block_t __end_block_addr(struct f2fs_sb_info *sbi) GET_SEGNO_FROM_SEG0(sbi, SM_I(sbi)->main_blkaddr) #define GET_R2L_SEGNO(sbi, segno) (segno + FREE_I_START_SEGNO(sbi)) +#define MAIN_SEGS(sbi) (SM_I(sbi)->main_segments) +#define TOTAL_BLKS(sbi) (TOTAL_SEGS(sbi) << (sbi)->log_blocks_per_seg) +#define MAX_BLKADDR(sbi) (SEG0_BLKADDR(sbi) + TOTAL_BLKS(sbi)) + #define START_BLOCK(sbi, segno) (SM_I(sbi)->main_blkaddr + \ ((segno) << sbi->log_blocks_per_seg)) +#define SIT_BLK_CNT(sbi) \ + ((MAIN_SEGS(sbi) + SIT_ENTRY_PER_BLOCK - 1) / SIT_ENTRY_PER_BLOCK) + static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type) { return (struct curseg_info *)(SM_I(sbi)->curseg_array + type); diff --git a/fsck/fsck.c b/fsck/fsck.c index b4e53db..eef829c 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -1673,6 +1673,8 @@ int fsck_chk_orphan_node(struct f2fs_sb_info *sbi) start_blk = __start_cp_addr(sbi) + 1 + get_sb(cp_payload); orphan_blkaddr = __start_sum_addr(sbi) - 1 - get_sb(cp_payload); + f2fs_ra_meta_pages(sbi, start_blk, orphan_blkaddr, META_CP); + orphan_blk = calloc(BLOCK_SZ, 1); ASSERT(orphan_blk); diff --git a/fsck/fsck.h b/fsck/fsck.h index 5733785..45f6517 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -180,6 +180,7 @@ extern int f2fs_set_sit_bitmap(struct f2fs_sb_info *, u32); extern void fsck_init(struct f2fs_sb_info *); extern int fsck_verify(struct f2fs_sb_info *); extern void fsck_free(struct f2fs_sb_info *); +extern int f2fs_ra_meta_pages(struct f2fs_sb_info *, block_t, int, int); extern int f2fs_do_mount(struct f2fs_sb_info *); extern void f2fs_do_umount(struct f2fs_sb_info *); extern int f2fs_sparse_initialize_meta(struct f2fs_sb_info *); diff --git a/fsck/mount.c b/fsck/mount.c index 5cfb900..ba0fa99 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -476,6 +476,94 @@ void print_sb_state(struct f2fs_super_block *sb) MSG(0, "\n"); } +bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi, + block_t blkaddr, int type) +{ + switch (type) { + case META_NAT: + break; + case META_SIT: + if (blkaddr >= SIT_BLK_CNT(sbi)) + return 0; + break; + case META_SSA: + if (blkaddr >= MAIN_BLKADDR(sbi) || + blkaddr < SM_I(sbi)->ssa_blkaddr) + return 0; + break; + case META_CP: + if (blkaddr >= SIT_I(sbi)->sit_base_addr || + blkaddr < __start_cp_addr(sbi)) + return 0; + break; + case META_POR: + if (blkaddr >= MAX_BLKADDR(sbi) || + blkaddr < MAIN_BLKADDR(sbi)) + return 0; + break; + default: + ASSERT(0); + } + + return 1; +} + +static inline block_t current_sit_addr(struct f2fs_sb_info *sbi, + unsigned int start); + +/* + * Readahead CP/NAT/SIT/SSA pages + */ +int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, + int type) +{ + block_t blkno = start; + block_t blkaddr, start_blk = 0, len = 0; + + for (; nrpages-- > 0; blkno++) { + + if (!f2fs_is_valid_blkaddr(sbi, blkno, type)) + goto out; + + switch (type) { + case META_NAT: + if (blkno >= NAT_BLOCK_OFFSET(NM_I(sbi)->max_nid)) + blkno = 0; + /* get nat block addr */ + blkaddr = current_nat_addr(sbi, + blkno * NAT_ENTRY_PER_BLOCK, NULL); + break; + case META_SIT: + /* get sit block addr */ + blkaddr = current_sit_addr(sbi, + blkno * SIT_ENTRY_PER_BLOCK); + break; + case META_SSA: + case META_CP: + case META_POR: + blkaddr = blkno; + break; + default: + ASSERT(0); + } + + if (!len) { + start_blk = blkaddr; + len = 1; + } else if (start_blk + len == blkaddr) { + len++; + } else { + dev_readahead(start_blk << F2FS_BLKSIZE_BITS, + len << F2FS_BLKSIZE_BITS); + } + } +out: + if (len) + dev_readahead(start_blk << F2FS_BLKSIZE_BITS, + len << F2FS_BLKSIZE_BITS); + return blkno - start; +} + void update_superblock(struct f2fs_super_block *sb, int sb_mask) { int addr, ret; @@ -1136,6 +1224,9 @@ static int f2fs_init_nid_bitmap(struct f2fs_sb_info *sbi) return -ENOMEM; } + f2fs_ra_meta_pages(sbi, 0, NAT_BLOCK_OFFSET(nm_i->max_nid), + META_NAT); + for (nid = 0; nid < nm_i->max_nid; nid++) { if (!(nid % NAT_ENTRY_PER_BLOCK)) { int ret; @@ -1986,7 +2077,9 @@ static int build_sit_entries(struct f2fs_sb_info *sbi) struct f2fs_sit_block *sit_blk; struct seg_entry *se; struct f2fs_sit_entry sit; - unsigned int i, segno; + int sit_blk_cnt = SIT_BLK_CNT(sbi); + unsigned int i, segno, end; + unsigned int readed, start_blk = 0; sit_blk = calloc(BLOCK_SZ, 1); if (!sit_blk) { @@ -1994,15 +2087,25 @@ static int build_sit_entries(struct f2fs_sb_info *sbi) return -ENOMEM; } - for (segno = 0; segno < TOTAL_SEGS(sbi); segno++) { - se = &sit_i->sentries[segno]; + do { + readed = f2fs_ra_meta_pages(sbi, start_blk, MAX_RA_BLOCKS, + META_SIT); - get_current_sit_page(sbi, segno, sit_blk); - sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, segno)]; + segno = start_blk * sit_i->sents_per_block; + end = (start_blk + readed) * sit_i->sents_per_block; + + for (; segno < end && segno < TOTAL_SEGS(sbi); segno++) { + se = &sit_i->sentries[segno]; + + get_current_sit_page(sbi, segno, sit_blk); + sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, segno)]; + + check_block_count(sbi, segno, &sit); + seg_info_from_raw_sit(se, &sit); + } + start_blk += readed; + } while (start_blk < sit_blk_cnt); - check_block_count(sbi, segno, &sit); - seg_info_from_raw_sit(se, &sit); - } free(sit_blk); diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 5b89572..84f3f3e 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -1186,6 +1186,11 @@ extern int f2fs_finalize_device(void); extern int f2fs_fsync_device(void); extern int dev_read(void *, __u64, size_t); +#ifdef POSIX_FADV_WILLNEED +extern int dev_readahead(__u64, size_t); +#else +extern int dev_readahead(__u64, size_t UNUSED(len)); +#endif extern int dev_write(void *, __u64, size_t); extern int dev_write_block(void *, __u64); extern int dev_write_dump(void *, __u64, size_t); -- 2.7.4