f2fs-tools: introduce f2fs_ra_meta_pages()
authorChao Yu <yuchao0@huawei.com>
Fri, 9 Aug 2019 10:52:57 +0000 (18:52 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Tue, 27 Aug 2019 21:51:05 +0000 (14:51 -0700)
Introduce f2fs_ra_meta_pages() to readahead meta pages like we did
in kernel.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fsck/f2fs.h
fsck/fsck.c
fsck/fsck.h
fsck/mount.c
include/f2fs_fs.h

index 6fc0bf3..52b81ff 100644 (file)
@@ -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);
index b4e53db..eef829c 100644 (file)
@@ -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);
 
index 5733785..45f6517 100644 (file)
@@ -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 *);
index 5cfb900..ba0fa99 100644 (file)
@@ -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);
 
index 5b89572..84f3f3e 100644 (file)
@@ -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);