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 <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Chao Yu 2019-08-09 18:52:57 +08:00 committed by Jaegeuk Kim
parent cd7c5020ce
commit 9e64efe276
5 changed files with 147 additions and 8 deletions

View 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);

View 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);

View 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 *);

View 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);

View 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);