diff options
Diffstat (limited to 'fs/f2fs/segment.c')
| -rw-r--r-- | fs/f2fs/segment.c | 101 |
1 files changed, 75 insertions, 26 deletions
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index a1acaa025bde..6dd1dc16a9d5 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/blkdev.h> | 14 | #include <linux/blkdev.h> |
| 15 | #include <linux/prefetch.h> | 15 | #include <linux/prefetch.h> |
| 16 | #include <linux/vmalloc.h> | 16 | #include <linux/vmalloc.h> |
| 17 | #include <linux/swap.h> | ||
| 17 | 18 | ||
| 18 | #include "f2fs.h" | 19 | #include "f2fs.h" |
| 19 | #include "segment.h" | 20 | #include "segment.h" |
| @@ -1706,41 +1707,89 @@ static int build_curseg(struct f2fs_sb_info *sbi) | |||
| 1706 | return restore_curseg_summaries(sbi); | 1707 | return restore_curseg_summaries(sbi); |
| 1707 | } | 1708 | } |
| 1708 | 1709 | ||
| 1710 | static int ra_sit_pages(struct f2fs_sb_info *sbi, int start, int nrpages) | ||
| 1711 | { | ||
| 1712 | struct address_space *mapping = sbi->meta_inode->i_mapping; | ||
| 1713 | struct page *page; | ||
| 1714 | block_t blk_addr, prev_blk_addr = 0; | ||
| 1715 | int sit_blk_cnt = SIT_BLK_CNT(sbi); | ||
| 1716 | int blkno = start; | ||
| 1717 | |||
| 1718 | for (; blkno < start + nrpages && blkno < sit_blk_cnt; blkno++) { | ||
| 1719 | |||
| 1720 | blk_addr = current_sit_addr(sbi, blkno * SIT_ENTRY_PER_BLOCK); | ||
| 1721 | |||
| 1722 | if (blkno != start && prev_blk_addr + 1 != blk_addr) | ||
| 1723 | break; | ||
| 1724 | prev_blk_addr = blk_addr; | ||
| 1725 | repeat: | ||
| 1726 | page = grab_cache_page(mapping, blk_addr); | ||
| 1727 | if (!page) { | ||
| 1728 | cond_resched(); | ||
| 1729 | goto repeat; | ||
| 1730 | } | ||
| 1731 | if (PageUptodate(page)) { | ||
| 1732 | mark_page_accessed(page); | ||
| 1733 | f2fs_put_page(page, 1); | ||
| 1734 | continue; | ||
| 1735 | } | ||
| 1736 | |||
| 1737 | submit_read_page(sbi, page, blk_addr, READ_SYNC); | ||
| 1738 | |||
| 1739 | mark_page_accessed(page); | ||
| 1740 | f2fs_put_page(page, 0); | ||
| 1741 | } | ||
| 1742 | |||
| 1743 | f2fs_submit_read_bio(sbi, READ_SYNC); | ||
| 1744 | return blkno - start; | ||
| 1745 | } | ||
| 1746 | |||
| 1709 | static void build_sit_entries(struct f2fs_sb_info *sbi) | 1747 | static void build_sit_entries(struct f2fs_sb_info *sbi) |
| 1710 | { | 1748 | { |
| 1711 | struct sit_info *sit_i = SIT_I(sbi); | 1749 | struct sit_info *sit_i = SIT_I(sbi); |
| 1712 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); | 1750 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); |
| 1713 | struct f2fs_summary_block *sum = curseg->sum_blk; | 1751 | struct f2fs_summary_block *sum = curseg->sum_blk; |
| 1714 | unsigned int start; | 1752 | int sit_blk_cnt = SIT_BLK_CNT(sbi); |
| 1715 | 1753 | unsigned int i, start, end; | |
| 1716 | for (start = 0; start < TOTAL_SEGS(sbi); start++) { | 1754 | unsigned int readed, start_blk = 0; |
| 1717 | struct seg_entry *se = &sit_i->sentries[start]; | 1755 | int nrpages = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); |
| 1718 | struct f2fs_sit_block *sit_blk; | ||
| 1719 | struct f2fs_sit_entry sit; | ||
| 1720 | struct page *page; | ||
| 1721 | int i; | ||
| 1722 | 1756 | ||
| 1723 | mutex_lock(&curseg->curseg_mutex); | 1757 | do { |
| 1724 | for (i = 0; i < sits_in_cursum(sum); i++) { | 1758 | readed = ra_sit_pages(sbi, start_blk, nrpages); |
| 1725 | if (le32_to_cpu(segno_in_journal(sum, i)) == start) { | 1759 | |
| 1726 | sit = sit_in_journal(sum, i); | 1760 | start = start_blk * sit_i->sents_per_block; |
| 1727 | mutex_unlock(&curseg->curseg_mutex); | 1761 | end = (start_blk + readed) * sit_i->sents_per_block; |
| 1728 | goto got_it; | 1762 | |
| 1763 | for (; start < end && start < TOTAL_SEGS(sbi); start++) { | ||
| 1764 | struct seg_entry *se = &sit_i->sentries[start]; | ||
| 1765 | struct f2fs_sit_block *sit_blk; | ||
| 1766 | struct f2fs_sit_entry sit; | ||
| 1767 | struct page *page; | ||
| 1768 | |||
| 1769 | mutex_lock(&curseg->curseg_mutex); | ||
| 1770 | for (i = 0; i < sits_in_cursum(sum); i++) { | ||
| 1771 | if (le32_to_cpu(segno_in_journal(sum, i)) == start) { | ||
| 1772 | sit = sit_in_journal(sum, i); | ||
| 1773 | mutex_unlock(&curseg->curseg_mutex); | ||
| 1774 | goto got_it; | ||
| 1775 | } | ||
| 1729 | } | 1776 | } |
| 1730 | } | 1777 | mutex_unlock(&curseg->curseg_mutex); |
| 1731 | mutex_unlock(&curseg->curseg_mutex); | 1778 | |
| 1732 | page = get_current_sit_page(sbi, start); | 1779 | page = get_current_sit_page(sbi, start); |
| 1733 | sit_blk = (struct f2fs_sit_block *)page_address(page); | 1780 | sit_blk = (struct f2fs_sit_block *)page_address(page); |
| 1734 | sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)]; | 1781 | sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)]; |
| 1735 | f2fs_put_page(page, 1); | 1782 | f2fs_put_page(page, 1); |
| 1736 | got_it: | 1783 | got_it: |
| 1737 | check_block_count(sbi, start, &sit); | 1784 | check_block_count(sbi, start, &sit); |
| 1738 | seg_info_from_raw_sit(se, &sit); | 1785 | seg_info_from_raw_sit(se, &sit); |
| 1739 | if (sbi->segs_per_sec > 1) { | 1786 | if (sbi->segs_per_sec > 1) { |
| 1740 | struct sec_entry *e = get_sec_entry(sbi, start); | 1787 | struct sec_entry *e = get_sec_entry(sbi, start); |
| 1741 | e->valid_blocks += se->valid_blocks; | 1788 | e->valid_blocks += se->valid_blocks; |
| 1789 | } | ||
| 1742 | } | 1790 | } |
| 1743 | } | 1791 | start_blk += readed; |
| 1792 | } while (start_blk < sit_blk_cnt); | ||
| 1744 | } | 1793 | } |
| 1745 | 1794 | ||
| 1746 | static void init_free_segmap(struct f2fs_sb_info *sbi) | 1795 | static void init_free_segmap(struct f2fs_sb_info *sbi) |
