aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2013-02-25 23:10:46 -0500
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-03-18 08:00:33 -0400
commit266e97a81cf73d1a0dac5f68391da382630a80b7 (patch)
treee5c335396c512c72d5c324f789a8ddae93340b0c
parent66d36a2944df461448159be5af13049dd2689e77 (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.c12
-rw-r--r--fs/f2fs/f2fs.h12
-rw-r--r--fs/f2fs/file.c8
-rw-r--r--fs/f2fs/node.c6
-rw-r--r--fs/f2fs/recovery.c2
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 /* 128enum {
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 */
387int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro) 387int 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);