diff options
author | Eric Sandeen <sandeen@redhat.com> | 2010-10-27 21:30:13 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-10-27 21:30:13 -0400 |
commit | 72f84e6560d18d60a091df27edf81409be6641cb (patch) | |
tree | e2fa11476b074f8526d620820f8b2e86e8a11412 | |
parent | 5b41d92437f1ae19b3f3ffa3b16589fd5df50ac0 (diff) |
ext4: update writeback_index based on last page scanned
As pointed out in a prior patch, updating the mapping's
writeback_index based on pages written isn't quite right;
what the writeback index is really supposed to reflect is
the next page which should be scanned for writeback during
periodic flush.
As in write_cache_pages(), write_cache_pages_da() does
this scanning for us as we assemble the mpd for later
writeout. If we keep track of the next page after the
current scan, we can easily update writeback_index without
worrying about pages written vs. pages skipped, etc.
Without this, an fsync will reset writeback_index to
0 (its starting index) + however many pages it wrote, which
can mess up the progress of periodic flush.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r-- | fs/ext4/inode.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c9ea95ba5fde..45fc5bdb7d67 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -2800,12 +2800,13 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode) | |||
2800 | */ | 2800 | */ |
2801 | static int write_cache_pages_da(struct address_space *mapping, | 2801 | static int write_cache_pages_da(struct address_space *mapping, |
2802 | struct writeback_control *wbc, | 2802 | struct writeback_control *wbc, |
2803 | struct mpage_da_data *mpd) | 2803 | struct mpage_da_data *mpd, |
2804 | pgoff_t *done_index) | ||
2804 | { | 2805 | { |
2805 | int ret = 0; | 2806 | int ret = 0; |
2806 | int done = 0; | 2807 | int done = 0; |
2807 | struct pagevec pvec; | 2808 | struct pagevec pvec; |
2808 | int nr_pages; | 2809 | unsigned nr_pages; |
2809 | pgoff_t index; | 2810 | pgoff_t index; |
2810 | pgoff_t end; /* Inclusive */ | 2811 | pgoff_t end; /* Inclusive */ |
2811 | long nr_to_write = wbc->nr_to_write; | 2812 | long nr_to_write = wbc->nr_to_write; |
@@ -2820,6 +2821,7 @@ static int write_cache_pages_da(struct address_space *mapping, | |||
2820 | else | 2821 | else |
2821 | tag = PAGECACHE_TAG_DIRTY; | 2822 | tag = PAGECACHE_TAG_DIRTY; |
2822 | 2823 | ||
2824 | *done_index = index; | ||
2823 | while (!done && (index <= end)) { | 2825 | while (!done && (index <= end)) { |
2824 | int i; | 2826 | int i; |
2825 | 2827 | ||
@@ -2843,6 +2845,8 @@ static int write_cache_pages_da(struct address_space *mapping, | |||
2843 | break; | 2845 | break; |
2844 | } | 2846 | } |
2845 | 2847 | ||
2848 | *done_index = page->index + 1; | ||
2849 | |||
2846 | lock_page(page); | 2850 | lock_page(page); |
2847 | 2851 | ||
2848 | /* | 2852 | /* |
@@ -2928,6 +2932,7 @@ static int ext4_da_writepages(struct address_space *mapping, | |||
2928 | long desired_nr_to_write, nr_to_writebump = 0; | 2932 | long desired_nr_to_write, nr_to_writebump = 0; |
2929 | loff_t range_start = wbc->range_start; | 2933 | loff_t range_start = wbc->range_start; |
2930 | struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb); | 2934 | struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb); |
2935 | pgoff_t done_index = 0; | ||
2931 | pgoff_t end; | 2936 | pgoff_t end; |
2932 | 2937 | ||
2933 | trace_ext4_da_writepages(inode, wbc); | 2938 | trace_ext4_da_writepages(inode, wbc); |
@@ -3050,7 +3055,7 @@ retry: | |||
3050 | mpd.io_done = 0; | 3055 | mpd.io_done = 0; |
3051 | mpd.pages_written = 0; | 3056 | mpd.pages_written = 0; |
3052 | mpd.retval = 0; | 3057 | mpd.retval = 0; |
3053 | ret = write_cache_pages_da(mapping, wbc, &mpd); | 3058 | ret = write_cache_pages_da(mapping, wbc, &mpd, &done_index); |
3054 | /* | 3059 | /* |
3055 | * If we have a contiguous extent of pages and we | 3060 | * If we have a contiguous extent of pages and we |
3056 | * haven't done the I/O yet, map the blocks and submit | 3061 | * haven't done the I/O yet, map the blocks and submit |
@@ -3104,14 +3109,13 @@ retry: | |||
3104 | __func__, wbc->nr_to_write, ret); | 3109 | __func__, wbc->nr_to_write, ret); |
3105 | 3110 | ||
3106 | /* Update index */ | 3111 | /* Update index */ |
3107 | index += pages_written; | ||
3108 | wbc->range_cyclic = range_cyclic; | 3112 | wbc->range_cyclic = range_cyclic; |
3109 | if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) | 3113 | if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) |
3110 | /* | 3114 | /* |
3111 | * set the writeback_index so that range_cyclic | 3115 | * set the writeback_index so that range_cyclic |
3112 | * mode will write it back later | 3116 | * mode will write it back later |
3113 | */ | 3117 | */ |
3114 | mapping->writeback_index = index; | 3118 | mapping->writeback_index = done_index; |
3115 | 3119 | ||
3116 | out_writepages: | 3120 | out_writepages: |
3117 | wbc->nr_to_write -= nr_to_writebump; | 3121 | wbc->nr_to_write -= nr_to_writebump; |