Re: [f2fs-dev] [PATCH] f2fs: introduce ra_meta_pages to readahead CP/NAT/SIT pages
Hi Kim, -Original Message- From: Jaegeuk Kim [mailto:jaegeuk@samsung.com] Sent: Friday, February 07, 2014 2:58 PM To: Chao Yu Cc: linux-fsde...@vger.kernel.org; linux-ker...@vger.kernel.org; linux-f2fs-devel@lists.sourceforge.net Subject: Re: [f2fs-dev] [PATCH] f2fs: introduce ra_meta_pages to readahead CP/NAT/SIT pages Hi Chao, Sorry for the delay. When I tested this patch, a deadlock was occurred, so I couldn't afford to look inside in more detail. When I see again, there is a bug wrt blkno. Please see below. You're right, and your code could fix this deadloop bug. Thanks for the test and review. :) I will send patch v2 later. 2014-01-28 (화), 10:28 +0800, Chao Yu: This patch help us to cleanup the readahead code by merging ra_{sit,nat}_pages function into ra_meta_pages. Additionally the new function is used to readahead cp block in recover_orphan_inodes. Signed-off-by: Chao Yu chao2...@samsung.com --- fs/f2fs/checkpoint.c | 78 ++ fs/f2fs/f2fs.h | 10 +++ fs/f2fs/node.c | 38 +--- fs/f2fs/segment.c| 43 +--- 4 files changed, 90 insertions(+), 79 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 293d048..a1986c3 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -75,6 +75,82 @@ out: return page; } +inline int get_max_meta_blks(struct f2fs_sb_info *sbi, int type) +{ + switch (type) { + case META_NAT: + return NM_I(sbi)-max_nid / NAT_ENTRY_PER_BLOCK; + case META_SIT: + return SIT_BLK_CNT(sbi); + case META_CP: + return 0; + default: + BUG(); + } +} + +/* + * Readahead CP/NAT/SIT pages + */ +int ra_meta_pages(struct f2fs_sb_info *sbi, int start, int nrpages, int type) +{ + struct address_space *mapping = sbi-meta_inode-i_mapping; We don't need to do this. Instead, we can use META_MAPPING(sbi) below. + struct page *page; + block_t blk_addr, prev_blk_addr = 0; + int blkno = start; + int max_blks = get_max_meta_blks(sbi, type); block_t prev_blk_addr = 0; struct page *page; int blkno = start; int max_blks = get_max_meta_blks(sbi, type); + struct f2fs_io_info fio = { + .type = META, + .rw = READ_SYNC | REQ_META | REQ_PRIO + }; + + for (blkno = start; blkno start + nrpages; blkno++) { for (; nrpages-- 0; blkno++) { block_t blk_addr; -- In the case of META_NAT, blkno becomes 0 if it hits max_blks. So, we should not use *blkno start + nrpages*. + + switch (type) { + case META_NAT: + /* get nat block addr */ + if (unlikely(blkno = max_blks)) + blkno = 0; + blk_addr = current_nat_addr(sbi, + blkno * NAT_ENTRY_PER_BLOCK); + break; + case META_SIT: + /* get sit block addr */ + if (unlikely(blkno = max_blks)) + goto out; + blk_addr = current_sit_addr(sbi, + blkno * SIT_ENTRY_PER_BLOCK); + if (blkno != start prev_blk_addr + 1 != blk_addr) + goto out; + prev_blk_addr = blk_addr; + break; + case META_CP: + /* get cp block addr */ + blk_addr = blkno; + break; + default: + BUG(); + } + + page = grab_cache_page(mapping, blk_addr); page = grab_cache_page(META_MAPPING(sbi), blk_addr); + if (!page) + continue; + if (PageUptodate(page)) { + mark_page_accessed(page); + f2fs_put_page(page, 1); + continue; + } + + f2fs_submit_page_mbio(sbi, page, blk_addr, fio); + mark_page_accessed(page); + f2fs_put_page(page, 0); + } +out: + f2fs_submit_merged_bio(sbi, META, READ); + return blkno - start; +} + static int f2fs_write_meta_page(struct page *page, struct writeback_control *wbc) { @@ -285,6 +361,8 @@ void recover_orphan_inodes(struct f2fs_sb_info *sbi) start_blk = __start_cp_addr(sbi) + 1; orphan_blkaddr = __start_sum_addr(sbi) - 1; + ra_meta_pages(sbi, start_blk, orphan_blkaddr, META_CP); + for (i = 0; i orphan_blkaddr; i++) { struct page *page = get_meta_page(sbi, start_blk + i); struct f2fs_orphan_block *orphan_blk; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
Re: [f2fs-dev] [PATCH] f2fs: introduce ra_meta_pages to readahead CP/NAT/SIT pages
Hi Chao, Sorry for the delay. When I tested this patch, a deadlock was occurred, so I couldn't afford to look inside in more detail. When I see again, there is a bug wrt blkno. Please see below. 2014-01-28 (화), 10:28 +0800, Chao Yu: This patch help us to cleanup the readahead code by merging ra_{sit,nat}_pages function into ra_meta_pages. Additionally the new function is used to readahead cp block in recover_orphan_inodes. Signed-off-by: Chao Yu chao2...@samsung.com --- fs/f2fs/checkpoint.c | 78 ++ fs/f2fs/f2fs.h | 10 +++ fs/f2fs/node.c | 38 +--- fs/f2fs/segment.c| 43 +--- 4 files changed, 90 insertions(+), 79 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 293d048..a1986c3 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -75,6 +75,82 @@ out: return page; } +inline int get_max_meta_blks(struct f2fs_sb_info *sbi, int type) +{ + switch (type) { + case META_NAT: + return NM_I(sbi)-max_nid / NAT_ENTRY_PER_BLOCK; + case META_SIT: + return SIT_BLK_CNT(sbi); + case META_CP: + return 0; + default: + BUG(); + } +} + +/* + * Readahead CP/NAT/SIT pages + */ +int ra_meta_pages(struct f2fs_sb_info *sbi, int start, int nrpages, int type) +{ + struct address_space *mapping = sbi-meta_inode-i_mapping; We don't need to do this. Instead, we can use META_MAPPING(sbi) below. + struct page *page; + block_t blk_addr, prev_blk_addr = 0; + int blkno = start; + int max_blks = get_max_meta_blks(sbi, type); block_t prev_blk_addr = 0; struct page *page; int blkno = start; int max_blks = get_max_meta_blks(sbi, type); + struct f2fs_io_info fio = { + .type = META, + .rw = READ_SYNC | REQ_META | REQ_PRIO + }; + + for (blkno = start; blkno start + nrpages; blkno++) { for (; nrpages-- 0; blkno++) { block_t blk_addr; -- In the case of META_NAT, blkno becomes 0 if it hits max_blks. So, we should not use *blkno start + nrpages*. + + switch (type) { + case META_NAT: + /* get nat block addr */ + if (unlikely(blkno = max_blks)) + blkno = 0; + blk_addr = current_nat_addr(sbi, + blkno * NAT_ENTRY_PER_BLOCK); + break; + case META_SIT: + /* get sit block addr */ + if (unlikely(blkno = max_blks)) + goto out; + blk_addr = current_sit_addr(sbi, + blkno * SIT_ENTRY_PER_BLOCK); + if (blkno != start prev_blk_addr + 1 != blk_addr) + goto out; + prev_blk_addr = blk_addr; + break; + case META_CP: + /* get cp block addr */ + blk_addr = blkno; + break; + default: + BUG(); + } + + page = grab_cache_page(mapping, blk_addr); page = grab_cache_page(META_MAPPING(sbi), blk_addr); + if (!page) + continue; + if (PageUptodate(page)) { + mark_page_accessed(page); + f2fs_put_page(page, 1); + continue; + } + + f2fs_submit_page_mbio(sbi, page, blk_addr, fio); + mark_page_accessed(page); + f2fs_put_page(page, 0); + } +out: + f2fs_submit_merged_bio(sbi, META, READ); + return blkno - start; +} + static int f2fs_write_meta_page(struct page *page, struct writeback_control *wbc) { @@ -285,6 +361,8 @@ void recover_orphan_inodes(struct f2fs_sb_info *sbi) start_blk = __start_cp_addr(sbi) + 1; orphan_blkaddr = __start_sum_addr(sbi) - 1; + ra_meta_pages(sbi, start_blk, orphan_blkaddr, META_CP); + for (i = 0; i orphan_blkaddr; i++) { struct page *page = get_meta_page(sbi, start_blk + i); struct f2fs_orphan_block *orphan_blk; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index af51a0b..69ffc1b 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -88,6 +88,15 @@ enum { SIT_BITMAP }; +/* + * For CP/NAT/SIT readahead + */ +enum { + META_CP, + META_NAT, + META_SIT +}; + /* for the list of orphan inodes */ struct orphan_inode_entry { struct list_head list; /* list head */ @@ -1158,6 +1167,7 @@ void destroy_segment_manager_caches(void); */ struct page *grab_meta_page(struct