[f2fs-dev] [PATCH 2/3] f2fs: lookup extent cache first under IPU scenario
Signed-off-by: Hou Pengyang Signed-off-by: Chao Yu --- fs/f2fs/data.c | 24 1 file changed, 24 insertions(+) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 6b18750..1c99ae1 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1367,8 +1367,32 @@ int do_write_data_page(struct f2fs_io_info *fio) struct page *page = fio->page; struct inode *inode = page->mapping->host; struct dnode_of_data dn; + struct extent_info ei = {0,0,0}; int err = 0; + /* +* If a page is cold, NOT atomit written and need_ipu now, there is +* a high probability that IPU should be adapted. For IPU, we try to +* check extent tree to get the block index first, instead of reading +* the dnode page, where may lead to an useless dnode IO, since no need to +* update the dnode index for IPU. +*/ + if (unlikely(need_inplace_update_block(fio, page) && + f2fs_lookup_extent_cache(inode, page->index, &ei))) { + + fio->old_blkaddr = ei.blk + page->index - ei.fofs; + + if (fio->old_blkaddr != NEW_ADDR && + fio->old_blkaddr != NULL_ADDR) { + err = f2fs_encrypt_page(fio, page); + if (err) + return err; + set_page_writeback(page); + err = do_rewrite_data_page(fio, page); + return err; + } + } + set_new_dnode(&dn, inode, NULL, NULL, 0); err = get_dnode_of_data(&dn, page->index, LOOKUP_NODE); if (err) -- 2.10.1 -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 1/3] f2fs: reconstruct code to write a data page
This patch introduces two functions: 1) f2fs_encrypt_page -- encrypt data page before submit_bio 2) do_rewrite_data_page -- IPU rewrite The two functions are extraced from do_write_data_page, logic in do_write_data_page stays unchanged. Signed-off-by: Hou Pengyang Signed-off-by: Chao Yu --- fs/f2fs/data.c | 83 -- 1 file changed, 58 insertions(+), 25 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index b8dcd1e..6b18750 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1302,26 +1302,11 @@ static int f2fs_read_data_pages(struct file *file, return f2fs_mpage_readpages(mapping, pages, NULL, nr_pages); } -int do_write_data_page(struct f2fs_io_info *fio) +static int f2fs_encrypt_page(struct f2fs_io_info *fio, struct page *page) { - struct page *page = fio->page; struct inode *inode = page->mapping->host; - struct dnode_of_data dn; int err = 0; - set_new_dnode(&dn, inode, NULL, NULL, 0); - err = get_dnode_of_data(&dn, page->index, LOOKUP_NODE); - if (err) - return err; - - fio->old_blkaddr = dn.data_blkaddr; - - /* This page is already truncated */ - if (fio->old_blkaddr == NULL_ADDR) { - ClearPageUptodate(page); - goto out_writepage; - } - if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) { gfp_t gfp_flags = GFP_NOFS; @@ -1343,9 +1328,63 @@ int do_write_data_page(struct f2fs_io_info *fio) err = 0; goto retry_encrypt; } - goto out_writepage; + return err; } } + return err; +} + +static int do_rewrite_data_page(struct f2fs_io_info *fio, struct page *page) +{ + struct inode *inode = page->mapping->host; + int err; + + f2fs_bug_on(F2FS_P_SB(page), !fio->cp_rwsem_locked); + + f2fs_unlock_op(F2FS_I_SB(inode)); + fio->cp_rwsem_locked = false; + err = rewrite_data_page(fio); + set_inode_flag(inode, FI_UPDATE_WRITE); + trace_f2fs_do_write_data_page(page, IPU); + return err; + +} + +static inline bool need_inplace_update_block(struct f2fs_io_info *fio, struct page *page) +{ + struct inode *inode = page->mapping->host; + + if (!is_cold_data(page) && + !IS_ATOMIC_WRITTEN_PAGE(page) && + need_inplace_update(inode, fio)) + return true; + + return false; +} + +int do_write_data_page(struct f2fs_io_info *fio) +{ + struct page *page = fio->page; + struct inode *inode = page->mapping->host; + struct dnode_of_data dn; + int err = 0; + + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, page->index, LOOKUP_NODE); + if (err) + return err; + + fio->old_blkaddr = dn.data_blkaddr; + + /* This page is already truncated */ + if (fio->old_blkaddr == NULL_ADDR) { + ClearPageUptodate(page); + goto out_writepage; + } + + err = f2fs_encrypt_page(fio, page); + if (err) + goto out_writepage; set_page_writeback(page); @@ -1354,14 +1393,8 @@ int do_write_data_page(struct f2fs_io_info *fio) * it had better in-place writes for updated data. */ if (unlikely(fio->old_blkaddr != NEW_ADDR && - !is_cold_data(page) && - !IS_ATOMIC_WRITTEN_PAGE(page) && - need_inplace_update(inode, fio))) { - f2fs_unlock_op(F2FS_I_SB(inode)); - fio->cp_rwsem_locked = false; - err = rewrite_data_page(fio); - set_inode_flag(inode, FI_UPDATE_WRITE); - trace_f2fs_do_write_data_page(page, IPU); + need_inplace_update_block(fio, page))) { + err = do_rewrite_data_page(fio, page); } else { write_data_page(&dn, fio); trace_f2fs_do_write_data_page(page, OPU); -- 2.10.1 -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 0/3] optimize f2fs IPU v2
For IPU, there is no need to read dnode, these three patches are to fix this issue. patch 1): Reconstruct code in do_write_data_page, code logic stays unchanged, patch 2): Under high-probability IPU scenario, we check extent_tree first patch 3): Unlock dnode before IPU v1->v2: 1) fix if(f2fs_encrypt_page()) XXX to err = f2fs_encrypt_page() if (err) XXX otherwise do_write_data_page would return a wrong return value. 2) extract need_in_place_block(fio, page) for IPU checking. Hou Pengyang (3): f2fs: reconstruct code to write a data page f2fs: lookup extent cache first under IPU scenario f2fs: unlock dnode before IPU fs/f2fs/data.c | 109 - 1 file changed, 84 insertions(+), 25 deletions(-) -- 2.10.1 -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 3/3] f2fs: unlock dnode before IPU
Signed-off-by: Hou Pengyang --- fs/f2fs/data.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 1c99ae1..a0df451 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1418,7 +1418,9 @@ int do_write_data_page(struct f2fs_io_info *fio) */ if (unlikely(fio->old_blkaddr != NEW_ADDR && need_inplace_update_block(fio, page))) { + f2fs_put_dnode(&dn); err = do_rewrite_data_page(fio, page); + return err; } else { write_data_page(&dn, fio); trace_f2fs_do_write_data_page(page, OPU); -- 2.10.1 -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH] f2fs: seperate read nat page from nat_tree_lock
This patch seperate nat page read io from nat_tree_lock. -lock_page -get_node_info() -current_nat_addr .. -> write_checkpoint -get_meta_page Because we lock node page, we can make sure no other threads modify this nid concurrently. So we just obtain current_nat_addr under nat_tree_lock, node info is always same in both nat pack. Signed-off-by: Yunlei He --- fs/f2fs/node.c | 11 --- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index ad54e90..b99e318 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -376,6 +376,7 @@ void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni) struct page *page = NULL; struct f2fs_nat_entry ne; struct nat_entry *e; + pgoff_t index; int i; ni->nid = nid; @@ -401,17 +402,21 @@ void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni) node_info_from_raw_nat(ni, &ne); } up_read(&curseg->journal_rwsem); - if (i >= 0) + if (i >= 0) { + up_read(&nm_i->nat_tree_lock); goto cache; + } /* Fill node_info from nat page */ - page = get_current_nat_page(sbi, start_nid); + index = current_nat_addr(sbi, nid); + up_read(&nm_i->nat_tree_lock); + + page = get_meta_page(sbi, index); nat_blk = (struct f2fs_nat_block *)page_address(page); ne = nat_blk->entries[nid - start_nid]; node_info_from_raw_nat(ni, &ne); f2fs_put_page(page, 1); cache: - up_read(&nm_i->nat_tree_lock); /* cache nat entry */ down_write(&nm_i->nat_tree_lock); cache_nat_entry(sbi, nid, &ne); -- 2.10.1 -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel