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: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
@@ -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,
|
|||||||
else
|
else
|
||||||
len = PAGE_CACHE_SIZE;
|
len = PAGE_CACHE_SIZE;
|
||||||
|
|
||||||
if (page_has_buffers(page)) {
|
/*
|
||||||
|
* If the page does not have buffers (for whatever reason),
|
||||||
|
* try to create them using block_prepare_write. If this
|
||||||
|
* fails, redirty the page and move on.
|
||||||
|
*/
|
||||||
|
if (!page_buffers(page)) {
|
||||||
|
if (block_prepare_write(page, 0, len,
|
||||||
|
noalloc_get_block_write)) {
|
||||||
|
redirty_page:
|
||||||
|
redirty_page_for_writepage(wbc, page);
|
||||||
|
unlock_page(page);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
commit_write = 1;
|
||||||
|
}
|
||||||
page_bufs = page_buffers(page);
|
page_bufs = page_buffers(page);
|
||||||
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)) {
|
||||||
/*
|
/*
|
||||||
* We don't want to do block allocation
|
* We don't want to do block allocation So redirty the
|
||||||
* So redirty the page and return
|
* page and return We may reach here when we do a
|
||||||
* We may reach here when we do a journal commit
|
* journal commit via
|
||||||
* via journal_submit_inode_data_buffers.
|
* journal_submit_inode_data_buffers. If we don't
|
||||||
* If we don't have mapping block we just ignore
|
* have mapping block we just ignore them. We can also
|
||||||
* them. We can also reach here via shrink_page_list
|
* reach here via shrink_page_list
|
||||||
*/
|
*/
|
||||||
redirty_page_for_writepage(wbc, page);
|
goto redirty_page;
|
||||||
unlock_page(page);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
/* check whether all are mapped and non delay */
|
|
||||||
if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
|
|
||||||
ext4_bh_delay_or_unwritten)) {
|
|
||||||
redirty_page_for_writepage(wbc, page);
|
|
||||||
unlock_page(page);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* We can't do block allocation here
|
|
||||||
* so just redity the page and unlock
|
|
||||||
* and return
|
|
||||||
*/
|
|
||||||
redirty_page_for_writepage(wbc, 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,
|
|||||||
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);
|
||||||
|
Reference in New Issue
Block a user