diff options
-rw-r--r-- | fs/btrfs/extent_io.c | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 5d66cb27e422..05a1c42e25bf 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -2104,6 +2104,16 @@ int extent_read_full_page(struct extent_io_tree *tree, struct page *page, | |||
2104 | return ret; | 2104 | return ret; |
2105 | } | 2105 | } |
2106 | 2106 | ||
2107 | static noinline void update_nr_written(struct page *page, | ||
2108 | struct writeback_control *wbc, | ||
2109 | unsigned long nr_written) | ||
2110 | { | ||
2111 | wbc->nr_to_write -= nr_written; | ||
2112 | if (wbc->range_cyclic || (wbc->nr_to_write > 0 && | ||
2113 | wbc->range_start == 0 && wbc->range_end == LLONG_MAX)) | ||
2114 | page->mapping->writeback_index = page->index + nr_written; | ||
2115 | } | ||
2116 | |||
2107 | /* | 2117 | /* |
2108 | * the writepage semantics are similar to regular writepage. extent | 2118 | * the writepage semantics are similar to regular writepage. extent |
2109 | * records are inserted to lock ranges in the tree, and as dirty areas | 2119 | * records are inserted to lock ranges in the tree, and as dirty areas |
@@ -2173,6 +2183,12 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, | |||
2173 | delalloc_end = 0; | 2183 | delalloc_end = 0; |
2174 | page_started = 0; | 2184 | page_started = 0; |
2175 | if (!epd->extent_locked) { | 2185 | if (!epd->extent_locked) { |
2186 | /* | ||
2187 | * make sure the wbc mapping index is at least updated | ||
2188 | * to this page. | ||
2189 | */ | ||
2190 | update_nr_written(page, wbc, 0); | ||
2191 | |||
2176 | while (delalloc_end < page_end) { | 2192 | while (delalloc_end < page_end) { |
2177 | nr_delalloc = find_lock_delalloc_range(inode, tree, | 2193 | nr_delalloc = find_lock_delalloc_range(inode, tree, |
2178 | page, | 2194 | page, |
@@ -2194,7 +2210,13 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, | |||
2194 | */ | 2210 | */ |
2195 | if (page_started) { | 2211 | if (page_started) { |
2196 | ret = 0; | 2212 | ret = 0; |
2197 | goto update_nr_written; | 2213 | /* |
2214 | * we've unlocked the page, so we can't update | ||
2215 | * the mapping's writeback index, just update | ||
2216 | * nr_to_write. | ||
2217 | */ | ||
2218 | wbc->nr_to_write -= nr_written; | ||
2219 | goto done_unlocked; | ||
2198 | } | 2220 | } |
2199 | } | 2221 | } |
2200 | lock_extent(tree, start, page_end, GFP_NOFS); | 2222 | lock_extent(tree, start, page_end, GFP_NOFS); |
@@ -2207,13 +2229,18 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, | |||
2207 | if (ret == -EAGAIN) { | 2229 | if (ret == -EAGAIN) { |
2208 | unlock_extent(tree, start, page_end, GFP_NOFS); | 2230 | unlock_extent(tree, start, page_end, GFP_NOFS); |
2209 | redirty_page_for_writepage(wbc, page); | 2231 | redirty_page_for_writepage(wbc, page); |
2232 | update_nr_written(page, wbc, nr_written); | ||
2210 | unlock_page(page); | 2233 | unlock_page(page); |
2211 | ret = 0; | 2234 | ret = 0; |
2212 | goto update_nr_written; | 2235 | goto done_unlocked; |
2213 | } | 2236 | } |
2214 | } | 2237 | } |
2215 | 2238 | ||
2216 | nr_written++; | 2239 | /* |
2240 | * we don't want to touch the inode after unlocking the page, | ||
2241 | * so we update the mapping writeback index now | ||
2242 | */ | ||
2243 | update_nr_written(page, wbc, nr_written + 1); | ||
2217 | 2244 | ||
2218 | end = page_end; | 2245 | end = page_end; |
2219 | if (test_range_bit(tree, start, page_end, EXTENT_DELALLOC, 0)) | 2246 | if (test_range_bit(tree, start, page_end, EXTENT_DELALLOC, 0)) |
@@ -2345,11 +2372,8 @@ done: | |||
2345 | unlock_extent(tree, unlock_start, page_end, GFP_NOFS); | 2372 | unlock_extent(tree, unlock_start, page_end, GFP_NOFS); |
2346 | unlock_page(page); | 2373 | unlock_page(page); |
2347 | 2374 | ||
2348 | update_nr_written: | 2375 | done_unlocked: |
2349 | wbc->nr_to_write -= nr_written; | 2376 | |
2350 | if (wbc->range_cyclic || (wbc->nr_to_write > 0 && | ||
2351 | wbc->range_start == 0 && wbc->range_end == LLONG_MAX)) | ||
2352 | page->mapping->writeback_index = page->index + nr_written; | ||
2353 | return 0; | 2377 | return 0; |
2354 | } | 2378 | } |
2355 | 2379 | ||