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

ext4: simplify ext4_writepage()

The actual code in ext4_writepage() is unnecessarily convoluted.
Simplify it so it is easier to understand, but otherwise logically
equivalent.
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 5a87b7a5
...@@ -2704,7 +2704,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate); ...@@ -2704,7 +2704,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate);
static int ext4_writepage(struct page *page, static int ext4_writepage(struct page *page,
struct writeback_control *wbc) struct writeback_control *wbc)
{ {
int ret = 0; int ret = 0, commit_write = 0;
loff_t size; loff_t size;
unsigned int len; unsigned int len;
struct buffer_head *page_bufs = NULL; struct buffer_head *page_bufs = NULL;
...@@ -2717,60 +2717,37 @@ static int ext4_writepage(struct page *page, ...@@ -2717,60 +2717,37 @@ static int ext4_writepage(struct page *page,
else else
len = PAGE_CACHE_SIZE; len = PAGE_CACHE_SIZE;
if (page_has_buffers(page)) {
page_bufs = page_buffers(page);
if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
ext4_bh_delay_or_unwritten)) {
/* /*
* We don't want to do block allocation * If the page does not have buffers (for whatever reason),
* So redirty the page and return * try to create them using block_prepare_write. If this
* We may reach here when we do a journal commit * fails, redirty the page and move on.
* via journal_submit_inode_data_buffers.
* If we don't have mapping block we just ignore
* them. We can also reach here via shrink_page_list
*/ */
if (!page_buffers(page)) {
if (block_prepare_write(page, 0, len,
noalloc_get_block_write)) {
redirty_page:
redirty_page_for_writepage(wbc, page); redirty_page_for_writepage(wbc, page);
unlock_page(page); unlock_page(page);
return 0; return 0;
} }
} else { commit_write = 1;
/* }
* The test for page_has_buffers() is subtle:
* We know the page is dirty but it lost buffers. That means
* that at some moment in time after write_begin()/write_end()
* has been called all buffers have been clean and thus they
* must have been written at least once. So they are all
* mapped and we can happily proceed with mapping them
* and writing the page.
*
* Try to initialize the buffer_heads and check whether
* all are mapped and non delay. We don't want to
* do block allocation here.
*/
ret = block_prepare_write(page, 0, len,
noalloc_get_block_write);
if (!ret) {
page_bufs = page_buffers(page); page_bufs = page_buffers(page);
/* check whether all are mapped and non delay */
if (walk_page_buffers(NULL, page_bufs, 0, len, NULL, if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
ext4_bh_delay_or_unwritten)) { ext4_bh_delay_or_unwritten)) {
redirty_page_for_writepage(wbc, page);
unlock_page(page);
return 0;
}
} else {
/* /*
* We can't do block allocation here * We don't want to do block allocation So redirty the
* so just redity the page and unlock * page and return We may reach here when we do a
* and return * journal commit via
* journal_submit_inode_data_buffers. If we don't
* have mapping block we just ignore them. We can also
* reach here via shrink_page_list
*/ */
redirty_page_for_writepage(wbc, page); goto redirty_page;
unlock_page(page);
return 0;
} }
if (commit_write)
/* 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)) {
/* /*
...@@ -2781,7 +2758,7 @@ static int ext4_writepage(struct page *page, ...@@ -2781,7 +2758,7 @@ static int ext4_writepage(struct page *page,
return __ext4_journalled_writepage(page, len); return __ext4_journalled_writepage(page, len);
} }
if (page_bufs && buffer_uninit(page_bufs)) { if (buffer_uninit(page_bufs)) {
ext4_set_bh_endio(page_bufs, inode); ext4_set_bh_endio(page_bufs, inode);
ret = block_write_full_page_endio(page, noalloc_get_block_write, ret = block_write_full_page_endio(page, noalloc_get_block_write,
wbc, ext4_end_io_buffer_write); wbc, ext4_end_io_buffer_write);
......
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