diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-02-25 23:10:46 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-03-18 08:00:33 -0400 |
commit | 266e97a81cf73d1a0dac5f68391da382630a80b7 (patch) | |
tree | e5c335396c512c72d5c324f789a8ddae93340b0c | |
parent | 66d36a2944df461448159be5af13049dd2689e77 (diff) |
f2fs: introduce readahead mode of node pages
Previously, f2fs reads several node pages ahead when get_dnode_of_data is called
with RDONLY_NODE flag.
And, this flag is set by the following functions.
- get_data_block_ro
- get_lock_data_page
- do_write_data_page
- truncate_blocks
- truncate_hole
However, this readahead mechanism is initially introduced for the use of
get_data_block_ro to enhance the sequential read performance.
So, let's clarify all the cases with the additional modes as follows.
enum {
ALLOC_NODE, /* allocate a new node page if needed */
LOOKUP_NODE, /* look up a node without readahead */
LOOKUP_NODE_RA, /*
* look up a node with readahead called
* by get_datablock_ro.
*/
}
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Reviewed-by: Namjae Jeon <namjae.jeon@samsung.com>
-rw-r--r-- | fs/f2fs/data.c | 12 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 12 | ||||
-rw-r--r-- | fs/f2fs/file.c | 8 | ||||
-rw-r--r-- | fs/f2fs/node.c | 6 | ||||
-rw-r--r-- | fs/f2fs/recovery.c | 2 |
5 files changed, 22 insertions, 18 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 7bd22a201125..277966a8547a 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -183,7 +183,7 @@ struct page *find_data_page(struct inode *inode, pgoff_t index) | |||
183 | f2fs_put_page(page, 0); | 183 | f2fs_put_page(page, 0); |
184 | 184 | ||
185 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 185 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
186 | err = get_dnode_of_data(&dn, index, RDONLY_NODE); | 186 | err = get_dnode_of_data(&dn, index, LOOKUP_NODE); |
187 | if (err) | 187 | if (err) |
188 | return ERR_PTR(err); | 188 | return ERR_PTR(err); |
189 | f2fs_put_dnode(&dn); | 189 | f2fs_put_dnode(&dn); |
@@ -222,7 +222,7 @@ struct page *get_lock_data_page(struct inode *inode, pgoff_t index) | |||
222 | int err; | 222 | int err; |
223 | 223 | ||
224 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 224 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
225 | err = get_dnode_of_data(&dn, index, RDONLY_NODE); | 225 | err = get_dnode_of_data(&dn, index, LOOKUP_NODE); |
226 | if (err) | 226 | if (err) |
227 | return ERR_PTR(err); | 227 | return ERR_PTR(err); |
228 | f2fs_put_dnode(&dn); | 228 | f2fs_put_dnode(&dn); |
@@ -262,7 +262,7 @@ struct page *get_new_data_page(struct inode *inode, pgoff_t index, | |||
262 | int err; | 262 | int err; |
263 | 263 | ||
264 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 264 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
265 | err = get_dnode_of_data(&dn, index, 0); | 265 | err = get_dnode_of_data(&dn, index, ALLOC_NODE); |
266 | if (err) | 266 | if (err) |
267 | return ERR_PTR(err); | 267 | return ERR_PTR(err); |
268 | 268 | ||
@@ -392,7 +392,7 @@ static int get_data_block_ro(struct inode *inode, sector_t iblock, | |||
392 | 392 | ||
393 | /* When reading holes, we need its node page */ | 393 | /* When reading holes, we need its node page */ |
394 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 394 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
395 | err = get_dnode_of_data(&dn, pgofs, RDONLY_NODE); | 395 | err = get_dnode_of_data(&dn, pgofs, LOOKUP_NODE_RA); |
396 | if (err) | 396 | if (err) |
397 | return (err == -ENOENT) ? 0 : err; | 397 | return (err == -ENOENT) ? 0 : err; |
398 | 398 | ||
@@ -443,7 +443,7 @@ int do_write_data_page(struct page *page) | |||
443 | int err = 0; | 443 | int err = 0; |
444 | 444 | ||
445 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 445 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
446 | err = get_dnode_of_data(&dn, page->index, RDONLY_NODE); | 446 | err = get_dnode_of_data(&dn, page->index, LOOKUP_NODE); |
447 | if (err) | 447 | if (err) |
448 | return err; | 448 | return err; |
449 | 449 | ||
@@ -607,7 +607,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, | |||
607 | mutex_lock_op(sbi, DATA_NEW); | 607 | mutex_lock_op(sbi, DATA_NEW); |
608 | 608 | ||
609 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 609 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
610 | err = get_dnode_of_data(&dn, index, 0); | 610 | err = get_dnode_of_data(&dn, index, ALLOC_NODE); |
611 | if (err) { | 611 | if (err) { |
612 | mutex_unlock_op(sbi, DATA_NEW); | 612 | mutex_unlock_op(sbi, DATA_NEW); |
613 | f2fs_put_page(page, 1); | 613 | f2fs_put_page(page, 1); |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index cc2213afdcc7..be7ae70b0b1d 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -125,11 +125,15 @@ static inline int update_sits_in_cursum(struct f2fs_summary_block *rs, int i) | |||
125 | * file keeping -1 as its node offset to | 125 | * file keeping -1 as its node offset to |
126 | * distinguish from index node blocks. | 126 | * distinguish from index node blocks. |
127 | */ | 127 | */ |
128 | #define RDONLY_NODE 1 /* | 128 | enum { |
129 | * specify a read-only mode when getting | 129 | ALLOC_NODE, /* allocate a new node page if needed */ |
130 | * a node block. 0 is read-write mode. | 130 | LOOKUP_NODE, /* look up a node without readahead */ |
131 | * used by get_dnode_of_data(). | 131 | LOOKUP_NODE_RA, /* |
132 | * look up a node with readahead called | ||
133 | * by get_datablock_ro. | ||
132 | */ | 134 | */ |
135 | }; | ||
136 | |||
133 | #define F2FS_LINK_MAX 32000 /* maximum link count per file */ | 137 | #define F2FS_LINK_MAX 32000 /* maximum link count per file */ |
134 | 138 | ||
135 | /* for in-memory extent cache entry */ | 139 | /* for in-memory extent cache entry */ |
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 958a46da19ae..269645e23519 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -43,7 +43,7 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, | |||
43 | 43 | ||
44 | /* block allocation */ | 44 | /* block allocation */ |
45 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 45 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
46 | err = get_dnode_of_data(&dn, page->index, 0); | 46 | err = get_dnode_of_data(&dn, page->index, ALLOC_NODE); |
47 | if (err) { | 47 | if (err) { |
48 | mutex_unlock_op(sbi, DATA_NEW); | 48 | mutex_unlock_op(sbi, DATA_NEW); |
49 | goto out; | 49 | goto out; |
@@ -258,7 +258,7 @@ static int truncate_blocks(struct inode *inode, u64 from) | |||
258 | mutex_lock_op(sbi, DATA_TRUNC); | 258 | mutex_lock_op(sbi, DATA_TRUNC); |
259 | 259 | ||
260 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 260 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
261 | err = get_dnode_of_data(&dn, free_from, RDONLY_NODE); | 261 | err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE); |
262 | if (err) { | 262 | if (err) { |
263 | if (err == -ENOENT) | 263 | if (err == -ENOENT) |
264 | goto free_next; | 264 | goto free_next; |
@@ -420,7 +420,7 @@ int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end) | |||
420 | 420 | ||
421 | mutex_lock_op(sbi, DATA_TRUNC); | 421 | mutex_lock_op(sbi, DATA_TRUNC); |
422 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 422 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
423 | err = get_dnode_of_data(&dn, index, RDONLY_NODE); | 423 | err = get_dnode_of_data(&dn, index, LOOKUP_NODE); |
424 | if (err) { | 424 | if (err) { |
425 | mutex_unlock_op(sbi, DATA_TRUNC); | 425 | mutex_unlock_op(sbi, DATA_TRUNC); |
426 | if (err == -ENOENT) | 426 | if (err == -ENOENT) |
@@ -504,7 +504,7 @@ static int expand_inode_data(struct inode *inode, loff_t offset, | |||
504 | mutex_lock_op(sbi, DATA_NEW); | 504 | mutex_lock_op(sbi, DATA_NEW); |
505 | 505 | ||
506 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 506 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
507 | ret = get_dnode_of_data(&dn, index, 0); | 507 | ret = get_dnode_of_data(&dn, index, ALLOC_NODE); |
508 | if (ret) { | 508 | if (ret) { |
509 | mutex_unlock_op(sbi, DATA_NEW); | 509 | mutex_unlock_op(sbi, DATA_NEW); |
510 | break; | 510 | break; |
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index efcada7becd5..65ec2eabb392 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c | |||
@@ -384,7 +384,7 @@ got: | |||
384 | /* | 384 | /* |
385 | * Caller should call f2fs_put_dnode(dn). | 385 | * Caller should call f2fs_put_dnode(dn). |
386 | */ | 386 | */ |
387 | int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro) | 387 | int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) |
388 | { | 388 | { |
389 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); | 389 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); |
390 | struct page *npage[4]; | 390 | struct page *npage[4]; |
@@ -411,7 +411,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro) | |||
411 | for (i = 1; i <= level; i++) { | 411 | for (i = 1; i <= level; i++) { |
412 | bool done = false; | 412 | bool done = false; |
413 | 413 | ||
414 | if (!nids[i] && !ro) { | 414 | if (!nids[i] && mode == ALLOC_NODE) { |
415 | mutex_lock_op(sbi, NODE_NEW); | 415 | mutex_lock_op(sbi, NODE_NEW); |
416 | 416 | ||
417 | /* alloc new node */ | 417 | /* alloc new node */ |
@@ -434,7 +434,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro) | |||
434 | alloc_nid_done(sbi, nids[i]); | 434 | alloc_nid_done(sbi, nids[i]); |
435 | mutex_unlock_op(sbi, NODE_NEW); | 435 | mutex_unlock_op(sbi, NODE_NEW); |
436 | done = true; | 436 | done = true; |
437 | } else if (ro && i == level && level > 1) { | 437 | } else if (mode == LOOKUP_NODE_RA && i == level && level > 1) { |
438 | npage[i] = get_node_page_ra(parent, offset[i - 1]); | 438 | npage[i] = get_node_page_ra(parent, offset[i - 1]); |
439 | if (IS_ERR(npage[i])) { | 439 | if (IS_ERR(npage[i])) { |
440 | err = PTR_ERR(npage[i]); | 440 | err = PTR_ERR(npage[i]); |
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index b235215ac138..6b82e2034cfd 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c | |||
@@ -247,7 +247,7 @@ static void do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | |||
247 | end = start + ADDRS_PER_BLOCK; | 247 | end = start + ADDRS_PER_BLOCK; |
248 | 248 | ||
249 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 249 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
250 | if (get_dnode_of_data(&dn, start, 0)) | 250 | if (get_dnode_of_data(&dn, start, ALLOC_NODE)) |
251 | return; | 251 | return; |
252 | 252 | ||
253 | wait_on_page_writeback(dn.node_page); | 253 | wait_on_page_writeback(dn.node_page); |