Skip to content
This repository was archived by the owner on Nov 21, 2022. It is now read-only.

Commit 3cf4574

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: introduce get_next_page_offset to speed up SEEK_DATA
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 <chao2.yu@samsung.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent 81ca735 commit 3cf4574

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

fs/f2fs/f2fs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,8 @@ struct dnode_of_data {
551551
unsigned int ofs_in_node; /* data offset in the node page */
552552
bool inode_page_locked; /* inode page is locked or not */
553553
bool node_changed; /* is node block changed */
554+
char cur_level; /* level of hole node page */
555+
char max_level; /* level of current page located */
554556
block_t data_blkaddr; /* block address of the node block */
555557
};
556558

@@ -1793,6 +1795,7 @@ int need_dentry_mark(struct f2fs_sb_info *, nid_t);
17931795
bool is_checkpointed_node(struct f2fs_sb_info *, nid_t);
17941796
bool need_inode_block_update(struct f2fs_sb_info *, nid_t);
17951797
void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *);
1798+
pgoff_t get_next_page_offset(struct dnode_of_data *, pgoff_t);
17961799
int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int);
17971800
int truncate_inode_blocks(struct inode *, pgoff_t);
17981801
int truncate_xattr_node(struct inode *, struct page *);

fs/f2fs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
358358
} else if (err == -ENOENT) {
359359
/* direct node does not exists */
360360
if (whence == SEEK_DATA) {
361-
pgofs = PGOFS_OF_NEXT_DNODE(pgofs, inode);
361+
pgofs = get_next_page_offset(&dn, pgofs);
362362
continue;
363363
} else {
364364
goto found;

fs/f2fs/node.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,37 @@ void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
403403
up_write(&nm_i->nat_tree_lock);
404404
}
405405

406+
pgoff_t get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs)
407+
{
408+
const long direct_index = ADDRS_PER_INODE(dn->inode);
409+
const long direct_blks = ADDRS_PER_BLOCK;
410+
const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
411+
unsigned int skipped_unit = ADDRS_PER_BLOCK;
412+
int cur_level = dn->cur_level;
413+
int max_level = dn->max_level;
414+
pgoff_t base = 0;
415+
416+
if (!dn->max_level)
417+
return pgofs + 1;
418+
419+
while (max_level-- > cur_level)
420+
skipped_unit *= NIDS_PER_BLOCK;
421+
422+
switch (dn->max_level) {
423+
case 3:
424+
base += 2 * indirect_blks;
425+
case 2:
426+
base += 2 * direct_blks;
427+
case 1:
428+
base += direct_index;
429+
break;
430+
default:
431+
f2fs_bug_on(F2FS_I_SB(dn->inode), 1);
432+
}
433+
434+
return ((pgofs - base) / skipped_unit + 1) * skipped_unit + base;
435+
}
436+
406437
/*
407438
* The maximum depth is four.
408439
* 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)
495526
int offset[4];
496527
unsigned int noffset[4];
497528
nid_t nids[4];
498-
int level, i;
529+
int level, i = 0;
499530
int err = 0;
500531

501532
level = get_node_path(dn->inode, index, offset, noffset);
@@ -585,6 +616,10 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
585616
release_out:
586617
dn->inode_page = NULL;
587618
dn->node_page = NULL;
619+
if (err == -ENOENT) {
620+
dn->cur_level = i;
621+
dn->max_level = level;
622+
}
588623
return err;
589624
}
590625

0 commit comments

Comments
 (0)