diff options
Diffstat (limited to 'fs/ext4/inode.c')
| -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); |
