diff options
author | Theodore Ts'o <tytso@mit.edu> | 2010-10-27 21:30:09 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-10-27 21:30:09 -0400 |
commit | cb20d5188366f04d96d2e07b1240cc92170ade40 (patch) | |
tree | 6fe424e1ccdd36f8b4a60e144cfdaa577296926e /fs | |
parent | a42afc5f56f319107e987aa6adf2f65d93d527c7 (diff) |
ext4: inline ext4_writepage() into mpage_da_submit_io()
As a prepratory step to switching to bio_submit, inline
ext4_writepage() into mpage_da_submit() and then simplify things a
bit. This makes it clearer what mpage_da_submit needs to do.
Also, move the ClearPageChecked(page) call into
__ext4_journalled_writepage(), as a minor bit of cleanup refactoring.
This also allows us to pull i_size_read() and
ext4_should_journal_data() out of the loop, which should be a very
minor CPU savings.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/inode.c | 70 |
1 files changed, 59 insertions, 11 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index a08ec795995f..97a0c35219ae 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -60,7 +60,12 @@ static inline int ext4_begin_ordered_truncate(struct inode *inode, | |||
60 | } | 60 | } |
61 | 61 | ||
62 | static void ext4_invalidatepage(struct page *page, unsigned long offset); | 62 | static void ext4_invalidatepage(struct page *page, unsigned long offset); |
63 | static int ext4_writepage(struct page *page, struct writeback_control *wbc); | 63 | static int noalloc_get_block_write(struct inode *inode, sector_t iblock, |
64 | struct buffer_head *bh_result, int create); | ||
65 | static int ext4_set_bh_endio(struct buffer_head *bh, struct inode *inode); | ||
66 | static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate); | ||
67 | static int __ext4_journalled_writepage(struct page *page, unsigned int len); | ||
68 | static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh); | ||
64 | 69 | ||
65 | /* | 70 | /* |
66 | * Test whether an inode is a fast symlink. | 71 | * Test whether an inode is a fast symlink. |
@@ -2000,12 +2005,15 @@ static void ext4_da_page_release_reservation(struct page *page, | |||
2000 | */ | 2005 | */ |
2001 | static int mpage_da_submit_io(struct mpage_da_data *mpd) | 2006 | static int mpage_da_submit_io(struct mpage_da_data *mpd) |
2002 | { | 2007 | { |
2003 | long pages_skipped; | ||
2004 | struct pagevec pvec; | 2008 | struct pagevec pvec; |
2005 | unsigned long index, end; | 2009 | unsigned long index, end; |
2006 | int ret = 0, err, nr_pages, i; | 2010 | int ret = 0, err, nr_pages, i; |
2007 | struct inode *inode = mpd->inode; | 2011 | struct inode *inode = mpd->inode; |
2008 | struct address_space *mapping = inode->i_mapping; | 2012 | struct address_space *mapping = inode->i_mapping; |
2013 | loff_t size = i_size_read(inode); | ||
2014 | unsigned int len; | ||
2015 | struct buffer_head *page_bufs = NULL; | ||
2016 | int journal_data = ext4_should_journal_data(inode); | ||
2009 | 2017 | ||
2010 | BUG_ON(mpd->next_page <= mpd->first_page); | 2018 | BUG_ON(mpd->next_page <= mpd->first_page); |
2011 | /* | 2019 | /* |
@@ -2023,28 +2031,69 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd) | |||
2023 | if (nr_pages == 0) | 2031 | if (nr_pages == 0) |
2024 | break; | 2032 | break; |
2025 | for (i = 0; i < nr_pages; i++) { | 2033 | for (i = 0; i < nr_pages; i++) { |
2034 | int commit_write = 0; | ||
2026 | struct page *page = pvec.pages[i]; | 2035 | struct page *page = pvec.pages[i]; |
2027 | 2036 | ||
2028 | index = page->index; | 2037 | index = page->index; |
2029 | if (index > end) | 2038 | if (index > end) |
2030 | break; | 2039 | break; |
2040 | |||
2041 | if (index == size >> PAGE_CACHE_SHIFT) | ||
2042 | len = size & ~PAGE_CACHE_MASK; | ||
2043 | else | ||
2044 | len = PAGE_CACHE_SIZE; | ||
2031 | index++; | 2045 | index++; |
2032 | 2046 | ||
2033 | BUG_ON(!PageLocked(page)); | 2047 | BUG_ON(!PageLocked(page)); |
2034 | BUG_ON(PageWriteback(page)); | 2048 | BUG_ON(PageWriteback(page)); |
2035 | 2049 | ||
2036 | pages_skipped = mpd->wbc->pages_skipped; | 2050 | /* |
2037 | err = ext4_writepage(page, mpd->wbc); | 2051 | * If the page does not have buffers (for |
2038 | if (!err && (pages_skipped == mpd->wbc->pages_skipped)) | 2052 | * whatever reason), try to create them using |
2053 | * block_prepare_write. If this fails, | ||
2054 | * redirty the page and move on. | ||
2055 | */ | ||
2056 | if (!page_has_buffers(page)) { | ||
2057 | if (block_prepare_write(page, 0, len, | ||
2058 | noalloc_get_block_write)) { | ||
2059 | redirty_page: | ||
2060 | redirty_page_for_writepage(mpd->wbc, | ||
2061 | page); | ||
2062 | unlock_page(page); | ||
2063 | continue; | ||
2064 | } | ||
2065 | commit_write = 1; | ||
2066 | } | ||
2067 | page_bufs = page_buffers(page); | ||
2068 | if (walk_page_buffers(NULL, page_bufs, 0, len, NULL, | ||
2069 | ext4_bh_delay_or_unwritten)) { | ||
2039 | /* | 2070 | /* |
2040 | * have successfully written the page | 2071 | * We couldn't do block allocation for |
2041 | * without skipping the same | 2072 | * some reason. |
2042 | */ | 2073 | */ |
2074 | goto redirty_page; | ||
2075 | } | ||
2076 | |||
2077 | if (commit_write) | ||
2078 | /* mark the buffer_heads as dirty & uptodate */ | ||
2079 | block_commit_write(page, 0, len); | ||
2080 | |||
2081 | if (journal_data && PageChecked(page)) | ||
2082 | err = __ext4_journalled_writepage(page, len); | ||
2083 | else if (buffer_uninit(page_bufs)) { | ||
2084 | ext4_set_bh_endio(page_bufs, inode); | ||
2085 | err = block_write_full_page_endio(page, | ||
2086 | noalloc_get_block_write, | ||
2087 | mpd->wbc, ext4_end_io_buffer_write); | ||
2088 | } else | ||
2089 | err = block_write_full_page(page, | ||
2090 | noalloc_get_block_write, mpd->wbc); | ||
2091 | |||
2092 | if (!err) | ||
2043 | mpd->pages_written++; | 2093 | mpd->pages_written++; |
2044 | /* | 2094 | /* |
2045 | * In error case, we have to continue because | 2095 | * In error case, we have to continue because |
2046 | * remaining pages are still locked | 2096 | * remaining pages are still locked |
2047 | * XXX: unlock and re-dirty them? | ||
2048 | */ | 2097 | */ |
2049 | if (ret == 0) | 2098 | if (ret == 0) |
2050 | ret = err; | 2099 | ret = err; |
@@ -2627,6 +2676,7 @@ static int __ext4_journalled_writepage(struct page *page, | |||
2627 | int ret = 0; | 2676 | int ret = 0; |
2628 | int err; | 2677 | int err; |
2629 | 2678 | ||
2679 | ClearPageChecked(page); | ||
2630 | page_bufs = page_buffers(page); | 2680 | page_bufs = page_buffers(page); |
2631 | BUG_ON(!page_bufs); | 2681 | BUG_ON(!page_bufs); |
2632 | walk_page_buffers(handle, page_bufs, 0, len, NULL, bget_one); | 2682 | walk_page_buffers(handle, page_bufs, 0, len, NULL, bget_one); |
@@ -2749,14 +2799,12 @@ static int ext4_writepage(struct page *page, | |||
2749 | /* now mark the buffer_heads as dirty and uptodate */ | 2799 | /* now mark the buffer_heads as dirty and uptodate */ |
2750 | block_commit_write(page, 0, len); | 2800 | block_commit_write(page, 0, len); |
2751 | 2801 | ||
2752 | if (PageChecked(page) && ext4_should_journal_data(inode)) { | 2802 | if (PageChecked(page) && ext4_should_journal_data(inode)) |
2753 | /* | 2803 | /* |
2754 | * It's mmapped pagecache. Add buffers and journal it. There | 2804 | * It's mmapped pagecache. Add buffers and journal it. There |
2755 | * doesn't seem much point in redirtying the page here. | 2805 | * doesn't seem much point in redirtying the page here. |
2756 | */ | 2806 | */ |
2757 | ClearPageChecked(page); | ||
2758 | return __ext4_journalled_writepage(page, len); | 2807 | return __ext4_journalled_writepage(page, len); |
2759 | } | ||
2760 | 2808 | ||
2761 | if (buffer_uninit(page_bufs)) { | 2809 | if (buffer_uninit(page_bufs)) { |
2762 | ext4_set_bh_endio(page_bufs, inode); | 2810 | ext4_set_bh_endio(page_bufs, inode); |