From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933108AbcAZHl4 (ORCPT ); Tue, 26 Jan 2016 02:41:56 -0500 Received: from mailout4.samsung.com ([203.254.224.34]:60254 "EHLO mailout4.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932135AbcAZHly (ORCPT ); Tue, 26 Jan 2016 02:41:54 -0500 X-AuditID: cbfee61a-f79266d000003652-7e-56a72340989b From: Chao Yu To: Jaegeuk Kim Cc: linux-f2fs-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org Subject: [PATCH 1/2] f2fs: introduce get_next_page_offset to speed up SEEK_DATA Date: Tue, 26 Jan 2016 15:40:44 +0800 Message-id: <009501d1580d$050f8f60$0f2eae20$@samsung.com> MIME-version: 1.0 Content-type: text/plain; charset=us-ascii Content-transfer-encoding: 7bit X-Mailer: Microsoft Outlook 14.0 Thread-index: AdFYDNWDBxB9Xz+AReu/D6YyfG3kRw== Content-language: zh-cn X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrNLMWRmVeSWpSXmKPExsVy+t9jAV0H5eVhBqfX6Vg8WT+L2eLSIneL y7vmsDkwe2xa1cnmsXvBZyaPz5vkApijuGxSUnMyy1KL9O0SuDKWf5zNVHBOvqLt1GSWBsa9 kl2MHBwSAiYSk//WdjFyApliEhfurWfrYuTiEBJYyihx5WEXC4TzilFi0qS5bCBVbAIqEss7 /jOB2CJA9qFFl9lBbGYBD4nGju+sILawgL/EvEP/mEFsFgFVielHm8DqeQUsJRZOPsECYQtK /Jh8jwWiV0ti/c7jTBC2vMTmNW+ZIS5SkNhx9jUjxC49iaunLrNC1IhLbDxyi2UCo8AsJKNm IRk1C8moWUhaFjCyrGKUSC1ILihOSs81zEst1ytOzC0uzUvXS87P3cQIDuJnUjsYD+5yP8Qo wMGoxMPLUbwsTIg1say4MvcQowQHs5IIrxLv8jAh3pTEyqrUovz4otKc1OJDjNIcLErivLWX IsOEBNITS1KzU1MLUotgskwcnFINjKK1JmziJpkHjGdl7dUR/L5xz1O/nWk3w7MWLaz2a20p 1GaOPsH+ukbZPIzp1/mbsSGrr4ooFaU8/n0jsWlVmpQ7QxZP9sHcX8vS1B5crHijUrTj1OSG ZQurvdwqji9T00hycTGdcWjazCNvr1vttJyqr7w197xHmccUz1O28XX35ocs9NRsVGIpzkg0 1GIuKk4EAF6QNydeAgAA Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When seeking data in ->llseek, if we encounter a big hole which covers several dnode pages, we will try to seek data from index of page which is the first page of next dnode page, at most we could skip searching (ADDRS_PER_BLOCK - 1) pages. However it's still not efficient, because if our indirect/double-indirect pointer are NULL, there are no dnode page locate in the tree indirect/ double-indirect pointer point to, it's not necessary to search the whole region. This patch introduces get_next_page_offset to calculate next page offset based on current searching level and max searching level returned from get_dnode_of_data, with this, we could skip searching the entire area indirect or double-indirect node block is not exist. Signed-off-by: Chao Yu --- fs/f2fs/f2fs.h | 3 +++ fs/f2fs/file.c | 2 +- fs/f2fs/node.c | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 4bcc512..3e1ba0a 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -552,6 +552,8 @@ struct dnode_of_data { unsigned int ofs_in_node; /* data offset in the node page */ bool inode_page_locked; /* inode page is locked or not */ bool node_changed; /* is node block changed */ + char cur_level; /* level of hole node page */ + char max_level; /* level of current page located */ block_t data_blkaddr; /* block address of the node block */ }; @@ -1783,6 +1785,7 @@ int need_dentry_mark(struct f2fs_sb_info *, nid_t); bool is_checkpointed_node(struct f2fs_sb_info *, nid_t); bool need_inode_block_update(struct f2fs_sb_info *, nid_t); void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *); +pgoff_t get_next_page_offset(struct dnode_of_data *, pgoff_t); int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int); int truncate_inode_blocks(struct inode *, pgoff_t); int truncate_xattr_node(struct inode *, struct page *); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index f2b14e3..2d73f14 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -358,7 +358,7 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence) } else if (err == -ENOENT) { /* direct node does not exists */ if (whence == SEEK_DATA) { - pgofs = PGOFS_OF_NEXT_DNODE(pgofs, inode); + pgofs = get_next_page_offset(&dn, pgofs); continue; } else { goto found; diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 97a4695..77a35f9 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -403,6 +403,37 @@ cache: up_write(&nm_i->nat_tree_lock); } +pgoff_t get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs) +{ + const long direct_index = ADDRS_PER_INODE(dn->inode); + const long direct_blks = ADDRS_PER_BLOCK; + const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK; + unsigned int skipped_unit = ADDRS_PER_BLOCK; + int cur_level = dn->cur_level; + int max_level = dn->max_level; + pgoff_t base = 0; + + if (!dn->max_level) + return pgofs + 1; + + while (max_level-- > cur_level) + skipped_unit *= NIDS_PER_BLOCK; + + switch (dn->max_level) { + case 3: + base += 2 * indirect_blks; + case 2: + base += 2 * direct_blks; + case 1: + base += direct_index; + break; + default: + f2fs_bug_on(F2FS_I_SB(dn->inode), 1); + } + + return ((pgofs - base) / skipped_unit + 1) * skipped_unit + base; +} + /* * The maximum depth is four. * Offset[0] will have raw inode offset. @@ -495,7 +526,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) int offset[4]; unsigned int noffset[4]; nid_t nids[4]; - int level, i; + int level, i = 0; int err = 0; level = get_node_path(dn->inode, index, offset, noffset); @@ -585,6 +616,10 @@ release_pages: release_out: dn->inode_page = NULL; dn->node_page = NULL; + if (err == -ENOENT) { + dn->cur_level = i; + dn->max_level = level; + } return err; } -- 2.7.0.2.g1b0b6dd