Commit cb20d518 authored by Theodore Ts'o's avatar Theodore Ts'o

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: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent a42afc5f
...@@ -60,7 +60,12 @@ static inline int ext4_begin_ordered_truncate(struct inode *inode, ...@@ -60,7 +60,12 @@ static inline int ext4_begin_ordered_truncate(struct inode *inode,
} }
static void ext4_invalidatepage(struct page *page, unsigned long offset); static void ext4_invalidatepage(struct page *page, unsigned long offset);
static int ext4_writepage(struct page *page, struct writeback_control *wbc); static int noalloc_get_block_write(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create);
static int ext4_set_bh_endio(struct buffer_head *bh, struct inode *inode);
static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate);
static int __ext4_journalled_writepage(struct page *page, unsigned int len);
static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh);
/* /*
* Test whether an inode is a fast symlink. * Test whether an inode is a fast symlink.
...@@ -2000,12 +2005,15 @@ static void ext4_da_page_release_reservation(struct page *page, ...@@ -2000,12 +2005,15 @@ static void ext4_da_page_release_reservation(struct page *page,
*/ */
static int mpage_da_submit_io(struct mpage_da_data *mpd) static int mpage_da_submit_io(struct mpage_da_data *mpd)
{ {
long pages_skipped;
struct pagevec pvec; struct pagevec pvec;
unsigned long index, end; unsigned long index, end;
int ret = 0, err, nr_pages, i; int ret = 0, err, nr_pages, i;
struct inode *inode = mpd->inode; struct inode *inode = mpd->inode;
struct address_space *mapping = inode->i_mapping; struct address_space *mapping = inode->i_mapping;
loff_t size = i_size_read(inode);
unsigned int len;
struct buffer_head *page_bufs = NULL;
int journal_data = ext4_should_journal_data(inode);
BUG_ON(mpd->next_page <= mpd->first_page); BUG_ON(mpd->next_page <= mpd->first_page);
/* /*
...@@ -2023,28 +2031,69 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd) ...@@ -2023,28 +2031,69 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd)
if (nr_pages == 0) if (nr_pages == 0)
break; break;
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
int commit_write = 0;
struct page *page = pvec.pages[i]; struct page *page = pvec.pages[i];
index = page->index; index = page->index;
if (index > end) if (index > end)
break; break;
if (index == size >> PAGE_CACHE_SHIFT)
len = size & ~PAGE_CACHE_MASK;
else
len = PAGE_CACHE_SIZE;
index++; index++;
BUG_ON(!PageLocked(page)); BUG_ON(!PageLocked(page));
BUG_ON(PageWriteback(page)); BUG_ON(PageWriteback(page));
pages_skipped = mpd->wbc->pages_skipped; /*
err = ext4_writepage(page, mpd->wbc); * If the page does not have buffers (for
if (!err && (pages_skipped == mpd->wbc->pages_skipped)) * whatever reason), try to create them using
* block_prepare_write. If this fails,
* redirty the page and move on.
*/
if (!page_has_buffers(page)) {
if (block_prepare_write(page, 0, len,
noalloc_get_block_write)) {
redirty_page:
redirty_page_for_writepage(mpd->wbc,
page);
unlock_page(page);
continue;
}
commit_write = 1;
}
page_bufs = page_buffers(page);
if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
ext4_bh_delay_or_unwritten)) {
/* /*
* have successfully written the page * We couldn't do block allocation for
* without skipping the same * some reason.
*/ */
goto redirty_page;
}
if (commit_write)
/* mark the buffer_heads as dirty & uptodate */
block_commit_write(page, 0, len);
if (journal_data && PageChecked(page))
err = __ext4_journalled_writepage(page, len);
else if (buffer_uninit(page_bufs)) {
ext4_set_bh_endio(page_bufs, inode);
err = block_write_full_page_endio(page,
noalloc_get_block_write,
mpd->wbc, ext4_end_io_buffer_write);
} else
err = block_write_full_page(page,
noalloc_get_block_write, mpd->wbc);
if (!err)
mpd->pages_written++; mpd->pages_written++;
/* /*
* In error case, we have to continue because * In error case, we have to continue because
* remaining pages are still locked * remaining pages are still locked
* XXX: unlock and re-dirty them?
*/ */
if (ret == 0) if (ret == 0)
ret = err; ret = err;
...@@ -2627,6 +2676,7 @@ static int __ext4_journalled_writepage(struct page *page, ...@@ -2627,6 +2676,7 @@ static int __ext4_journalled_writepage(struct page *page,
int ret = 0; int ret = 0;
int err; int err;
ClearPageChecked(page);
page_bufs = page_buffers(page); page_bufs = page_buffers(page);
BUG_ON(!page_bufs); BUG_ON(!page_bufs);
walk_page_buffers(handle, page_bufs, 0, len, NULL, bget_one); walk_page_buffers(handle, page_bufs, 0, len, NULL, bget_one);
...@@ -2749,14 +2799,12 @@ static int ext4_writepage(struct page *page, ...@@ -2749,14 +2799,12 @@ static int ext4_writepage(struct page *page,
/* now mark the buffer_heads as dirty and uptodate */ /* now mark the buffer_heads as dirty and uptodate */
block_commit_write(page, 0, len); block_commit_write(page, 0, len);
if (PageChecked(page) && ext4_should_journal_data(inode)) { if (PageChecked(page) && ext4_should_journal_data(inode))
/* /*
* It's mmapped pagecache. Add buffers and journal it. There * It's mmapped pagecache. Add buffers and journal it. There
* doesn't seem much point in redirtying the page here. * doesn't seem much point in redirtying the page here.
*/ */
ClearPageChecked(page);
return __ext4_journalled_writepage(page, len); return __ext4_journalled_writepage(page, len);
}
if (buffer_uninit(page_bufs)) { if (buffer_uninit(page_bufs)) {
ext4_set_bh_endio(page_bufs, inode); ext4_set_bh_endio(page_bufs, inode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment