diff options
author | Chao Yu <chao2.yu@samsung.com> | 2013-11-22 02:48:54 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-12-22 20:18:05 -0500 |
commit | 9af0ff1c527ebb267d9a3b6aa8af93c5843d4390 (patch) | |
tree | 4255b05374f6b6c76c0abf1f3d65f33be367cfbb /fs/f2fs | |
parent | 93dfe2ac516250755f7d5edd438b0ce67c0e3aa6 (diff) |
f2fs: readahead contiguous pages for restore_node_summary
If cp has no CP_UMOUNT_FLAG, we will read all pages in whole node segment
one by one, it makes low performance. So let's merge contiguous pages and
readahead for better performance.
Signed-off-by: Chao Yu <chao2.yu@samsung.com>
[Jaegeuk Kim: adjust the new bio operations]
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs')
-rw-r--r-- | fs/f2fs/node.c | 89 |
1 files changed, 63 insertions, 26 deletions
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 0e1a3df18e58..0855168af7d7 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c | |||
@@ -1565,47 +1565,84 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) | |||
1565 | return 0; | 1565 | return 0; |
1566 | } | 1566 | } |
1567 | 1567 | ||
1568 | /* | ||
1569 | * ra_sum_pages() merge contiguous pages into one bio and submit. | ||
1570 | * these pre-readed pages are linked in pages list. | ||
1571 | */ | ||
1572 | static int ra_sum_pages(struct f2fs_sb_info *sbi, struct list_head *pages, | ||
1573 | int start, int nrpages) | ||
1574 | { | ||
1575 | struct page *page; | ||
1576 | int page_idx = start; | ||
1577 | |||
1578 | for (; page_idx < start + nrpages; page_idx++) { | ||
1579 | /* alloc temporal page for read node summary info*/ | ||
1580 | page = alloc_page(GFP_NOFS | __GFP_ZERO); | ||
1581 | if (!page) { | ||
1582 | struct page *tmp; | ||
1583 | list_for_each_entry_safe(page, tmp, pages, lru) { | ||
1584 | list_del(&page->lru); | ||
1585 | unlock_page(page); | ||
1586 | __free_pages(page, 0); | ||
1587 | } | ||
1588 | return -ENOMEM; | ||
1589 | } | ||
1590 | |||
1591 | lock_page(page); | ||
1592 | page->index = page_idx; | ||
1593 | list_add_tail(&page->lru, pages); | ||
1594 | } | ||
1595 | |||
1596 | list_for_each_entry(page, pages, lru) | ||
1597 | f2fs_submit_page_mbio(sbi, page, page->index, META, READ); | ||
1598 | |||
1599 | f2fs_submit_merged_bio(sbi, META, true, READ); | ||
1600 | return 0; | ||
1601 | } | ||
1602 | |||
1568 | int restore_node_summary(struct f2fs_sb_info *sbi, | 1603 | int restore_node_summary(struct f2fs_sb_info *sbi, |
1569 | unsigned int segno, struct f2fs_summary_block *sum) | 1604 | unsigned int segno, struct f2fs_summary_block *sum) |
1570 | { | 1605 | { |
1571 | struct f2fs_node *rn; | 1606 | struct f2fs_node *rn; |
1572 | struct f2fs_summary *sum_entry; | 1607 | struct f2fs_summary *sum_entry; |
1573 | struct page *page; | 1608 | struct page *page, *tmp; |
1574 | block_t addr; | 1609 | block_t addr; |
1575 | int i, last_offset; | 1610 | int bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); |
1576 | 1611 | int i, last_offset, nrpages, err = 0; | |
1577 | /* alloc temporal page for read node */ | 1612 | LIST_HEAD(page_list); |
1578 | page = alloc_page(GFP_NOFS | __GFP_ZERO); | ||
1579 | if (!page) | ||
1580 | return -ENOMEM; | ||
1581 | lock_page(page); | ||
1582 | 1613 | ||
1583 | /* scan the node segment */ | 1614 | /* scan the node segment */ |
1584 | last_offset = sbi->blocks_per_seg; | 1615 | last_offset = sbi->blocks_per_seg; |
1585 | addr = START_BLOCK(sbi, segno); | 1616 | addr = START_BLOCK(sbi, segno); |
1586 | sum_entry = &sum->entries[0]; | 1617 | sum_entry = &sum->entries[0]; |
1587 | 1618 | ||
1588 | for (i = 0; i < last_offset; i++, sum_entry++) { | 1619 | for (i = 0; i < last_offset; i += nrpages, addr += nrpages) { |
1589 | /* | 1620 | nrpages = min(last_offset - i, bio_blocks); |
1590 | * In order to read next node page, | ||
1591 | * we must clear PageUptodate flag. | ||
1592 | */ | ||
1593 | ClearPageUptodate(page); | ||
1594 | 1621 | ||
1595 | if (f2fs_submit_page_bio(sbi, page, addr, READ_SYNC)) | 1622 | /* read ahead node pages */ |
1596 | goto out; | 1623 | err = ra_sum_pages(sbi, &page_list, addr, nrpages); |
1624 | if (err) | ||
1625 | return err; | ||
1597 | 1626 | ||
1598 | lock_page(page); | 1627 | list_for_each_entry_safe(page, tmp, &page_list, lru) { |
1599 | rn = F2FS_NODE(page); | 1628 | |
1600 | sum_entry->nid = rn->footer.nid; | 1629 | lock_page(page); |
1601 | sum_entry->version = 0; | 1630 | if(PageUptodate(page)) { |
1602 | sum_entry->ofs_in_node = 0; | 1631 | rn = F2FS_NODE(page); |
1603 | addr++; | 1632 | sum_entry->nid = rn->footer.nid; |
1633 | sum_entry->version = 0; | ||
1634 | sum_entry->ofs_in_node = 0; | ||
1635 | sum_entry++; | ||
1636 | } else { | ||
1637 | err = -EIO; | ||
1638 | } | ||
1639 | |||
1640 | list_del(&page->lru); | ||
1641 | unlock_page(page); | ||
1642 | __free_pages(page, 0); | ||
1643 | } | ||
1604 | } | 1644 | } |
1605 | unlock_page(page); | 1645 | return err; |
1606 | out: | ||
1607 | __free_pages(page, 0); | ||
1608 | return 0; | ||
1609 | } | 1646 | } |
1610 | 1647 | ||
1611 | static bool flush_nats_in_journal(struct f2fs_sb_info *sbi) | 1648 | static bool flush_nats_in_journal(struct f2fs_sb_info *sbi) |