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 | a42afc5f56f319107e987aa6adf2f65d93d527c7 (patch) | |
tree | 845d03a8cec3fcb705ea6c821d202c816de76655 /fs/ext4 | |
parent | 5a87b7a5da250c9be6d757758425dfeaf8ed3179 (diff) |
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>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/inode.c | 73 |
1 files changed, 25 insertions, 48 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 55961ff4efc2..a08ec795995f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -2704,7 +2704,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate); | |||
2704 | static int ext4_writepage(struct page *page, | 2704 | static int ext4_writepage(struct page *page, |
2705 | struct writeback_control *wbc) | 2705 | struct writeback_control *wbc) |
2706 | { | 2706 | { |
2707 | int ret = 0; | 2707 | int ret = 0, commit_write = 0; |
2708 | loff_t size; | 2708 | loff_t size; |
2709 | unsigned int len; | 2709 | unsigned int len; |
2710 | struct buffer_head *page_bufs = NULL; | 2710 | struct buffer_head *page_bufs = NULL; |
@@ -2717,60 +2717,37 @@ static int ext4_writepage(struct page *page, | |||
2717 | else | 2717 | else |
2718 | len = PAGE_CACHE_SIZE; | 2718 | len = PAGE_CACHE_SIZE; |
2719 | 2719 | ||
2720 | if (page_has_buffers(page)) { | 2720 | /* |
2721 | page_bufs = page_buffers(page); | 2721 | * If the page does not have buffers (for whatever reason), |
2722 | if (walk_page_buffers(NULL, page_bufs, 0, len, NULL, | 2722 | * try to create them using block_prepare_write. If this |
2723 | ext4_bh_delay_or_unwritten)) { | 2723 | * fails, redirty the page and move on. |
2724 | /* | 2724 | */ |
2725 | * We don't want to do block allocation | 2725 | if (!page_buffers(page)) { |
2726 | * So redirty the page and return | 2726 | if (block_prepare_write(page, 0, len, |
2727 | * We may reach here when we do a journal commit | 2727 | noalloc_get_block_write)) { |
2728 | * via journal_submit_inode_data_buffers. | 2728 | redirty_page: |
2729 | * If we don't have mapping block we just ignore | ||
2730 | * them. We can also reach here via shrink_page_list | ||
2731 | */ | ||
2732 | redirty_page_for_writepage(wbc, page); | 2729 | redirty_page_for_writepage(wbc, page); |
2733 | unlock_page(page); | 2730 | unlock_page(page); |
2734 | return 0; | 2731 | return 0; |
2735 | } | 2732 | } |
2736 | } else { | 2733 | commit_write = 1; |
2734 | } | ||
2735 | page_bufs = page_buffers(page); | ||
2736 | if (walk_page_buffers(NULL, page_bufs, 0, len, NULL, | ||
2737 | ext4_bh_delay_or_unwritten)) { | ||
2737 | /* | 2738 | /* |
2738 | * The test for page_has_buffers() is subtle: | 2739 | * We don't want to do block allocation So redirty the |
2739 | * We know the page is dirty but it lost buffers. That means | 2740 | * page and return We may reach here when we do a |
2740 | * that at some moment in time after write_begin()/write_end() | 2741 | * journal commit via |
2741 | * has been called all buffers have been clean and thus they | 2742 | * journal_submit_inode_data_buffers. If we don't |
2742 | * must have been written at least once. So they are all | 2743 | * have mapping block we just ignore them. We can also |
2743 | * mapped and we can happily proceed with mapping them | 2744 | * reach here via shrink_page_list |
2744 | * and writing the page. | ||
2745 | * | ||
2746 | * Try to initialize the buffer_heads and check whether | ||
2747 | * all are mapped and non delay. We don't want to | ||
2748 | * do block allocation here. | ||
2749 | */ | 2745 | */ |
2750 | ret = block_prepare_write(page, 0, len, | 2746 | goto redirty_page; |
2751 | noalloc_get_block_write); | 2747 | } |
2752 | if (!ret) { | 2748 | if (commit_write) |
2753 | page_bufs = page_buffers(page); | ||
2754 | /* check whether all are mapped and non delay */ | ||
2755 | if (walk_page_buffers(NULL, page_bufs, 0, len, NULL, | ||
2756 | ext4_bh_delay_or_unwritten)) { | ||
2757 | redirty_page_for_writepage(wbc, page); | ||
2758 | unlock_page(page); | ||
2759 | return 0; | ||
2760 | } | ||
2761 | } else { | ||
2762 | /* | ||
2763 | * We can't do block allocation here | ||
2764 | * so just redity the page and unlock | ||
2765 | * and return | ||
2766 | */ | ||
2767 | redirty_page_for_writepage(wbc, page); | ||
2768 | unlock_page(page); | ||
2769 | return 0; | ||
2770 | } | ||
2771 | /* now mark the buffer_heads as dirty and uptodate */ | 2749 | /* now mark the buffer_heads as dirty and uptodate */ |
2772 | block_commit_write(page, 0, len); | 2750 | block_commit_write(page, 0, len); |
2773 | } | ||
2774 | 2751 | ||
2775 | if (PageChecked(page) && ext4_should_journal_data(inode)) { | 2752 | if (PageChecked(page) && ext4_should_journal_data(inode)) { |
2776 | /* | 2753 | /* |
@@ -2781,7 +2758,7 @@ static int ext4_writepage(struct page *page, | |||
2781 | return __ext4_journalled_writepage(page, len); | 2758 | return __ext4_journalled_writepage(page, len); |
2782 | } | 2759 | } |
2783 | 2760 | ||
2784 | if (page_bufs && buffer_uninit(page_bufs)) { | 2761 | if (buffer_uninit(page_bufs)) { |
2785 | ext4_set_bh_endio(page_bufs, inode); | 2762 | ext4_set_bh_endio(page_bufs, inode); |
2786 | ret = block_write_full_page_endio(page, noalloc_get_block_write, | 2763 | ret = block_write_full_page_endio(page, noalloc_get_block_write, |
2787 | wbc, ext4_end_io_buffer_write); | 2764 | wbc, ext4_end_io_buffer_write); |