diff options
author | Ingo Molnar <mingo@elte.hu> | 2012-03-14 02:44:11 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2012-03-14 02:44:11 -0400 |
commit | cd593accdcc27ccbe6498d9ad1c2b6cc8e1d830d (patch) | |
tree | 9424d3ac86e753706cc6c3d7e6072d2a73711e29 /fs/btrfs/extent_io.c | |
parent | 11b91d6fe7272452c999573bab33c15c2f03dc31 (diff) | |
parent | fde7d9049e55ab85a390be7f415d74c9f62dd0f9 (diff) |
Merge tag 'v3.3-rc7' into x86/mce
Merge reason: Update from an ancient -rc1 base to an almost-final stable kernel.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 115 |
1 files changed, 67 insertions, 48 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 9d09a4f81875..a55fbe6252de 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -513,6 +513,15 @@ hit_next: | |||
513 | WARN_ON(state->end < start); | 513 | WARN_ON(state->end < start); |
514 | last_end = state->end; | 514 | last_end = state->end; |
515 | 515 | ||
516 | if (state->end < end && !need_resched()) | ||
517 | next_node = rb_next(&state->rb_node); | ||
518 | else | ||
519 | next_node = NULL; | ||
520 | |||
521 | /* the state doesn't have the wanted bits, go ahead */ | ||
522 | if (!(state->state & bits)) | ||
523 | goto next; | ||
524 | |||
516 | /* | 525 | /* |
517 | * | ---- desired range ---- | | 526 | * | ---- desired range ---- | |
518 | * | state | or | 527 | * | state | or |
@@ -565,20 +574,15 @@ hit_next: | |||
565 | goto out; | 574 | goto out; |
566 | } | 575 | } |
567 | 576 | ||
568 | if (state->end < end && prealloc && !need_resched()) | ||
569 | next_node = rb_next(&state->rb_node); | ||
570 | else | ||
571 | next_node = NULL; | ||
572 | |||
573 | set |= clear_state_bit(tree, state, &bits, wake); | 577 | set |= clear_state_bit(tree, state, &bits, wake); |
578 | next: | ||
574 | if (last_end == (u64)-1) | 579 | if (last_end == (u64)-1) |
575 | goto out; | 580 | goto out; |
576 | start = last_end + 1; | 581 | start = last_end + 1; |
577 | if (start <= end && next_node) { | 582 | if (start <= end && next_node) { |
578 | state = rb_entry(next_node, struct extent_state, | 583 | state = rb_entry(next_node, struct extent_state, |
579 | rb_node); | 584 | rb_node); |
580 | if (state->start == start) | 585 | goto hit_next; |
581 | goto hit_next; | ||
582 | } | 586 | } |
583 | goto search_again; | 587 | goto search_again; |
584 | 588 | ||
@@ -961,8 +965,6 @@ hit_next: | |||
961 | 965 | ||
962 | set_state_bits(tree, state, &bits); | 966 | set_state_bits(tree, state, &bits); |
963 | clear_state_bit(tree, state, &clear_bits, 0); | 967 | clear_state_bit(tree, state, &clear_bits, 0); |
964 | |||
965 | merge_state(tree, state); | ||
966 | if (last_end == (u64)-1) | 968 | if (last_end == (u64)-1) |
967 | goto out; | 969 | goto out; |
968 | 970 | ||
@@ -1007,7 +1009,6 @@ hit_next: | |||
1007 | if (state->end <= end) { | 1009 | if (state->end <= end) { |
1008 | set_state_bits(tree, state, &bits); | 1010 | set_state_bits(tree, state, &bits); |
1009 | clear_state_bit(tree, state, &clear_bits, 0); | 1011 | clear_state_bit(tree, state, &clear_bits, 0); |
1010 | merge_state(tree, state); | ||
1011 | if (last_end == (u64)-1) | 1012 | if (last_end == (u64)-1) |
1012 | goto out; | 1013 | goto out; |
1013 | start = last_end + 1; | 1014 | start = last_end + 1; |
@@ -1068,8 +1069,6 @@ hit_next: | |||
1068 | 1069 | ||
1069 | set_state_bits(tree, prealloc, &bits); | 1070 | set_state_bits(tree, prealloc, &bits); |
1070 | clear_state_bit(tree, prealloc, &clear_bits, 0); | 1071 | clear_state_bit(tree, prealloc, &clear_bits, 0); |
1071 | |||
1072 | merge_state(tree, prealloc); | ||
1073 | prealloc = NULL; | 1072 | prealloc = NULL; |
1074 | goto out; | 1073 | goto out; |
1075 | } | 1074 | } |
@@ -2154,13 +2153,46 @@ static int bio_readpage_error(struct bio *failed_bio, struct page *page, | |||
2154 | "this_mirror=%d, num_copies=%d, in_validation=%d\n", read_mode, | 2153 | "this_mirror=%d, num_copies=%d, in_validation=%d\n", read_mode, |
2155 | failrec->this_mirror, num_copies, failrec->in_validation); | 2154 | failrec->this_mirror, num_copies, failrec->in_validation); |
2156 | 2155 | ||
2157 | tree->ops->submit_bio_hook(inode, read_mode, bio, failrec->this_mirror, | 2156 | ret = tree->ops->submit_bio_hook(inode, read_mode, bio, |
2158 | failrec->bio_flags, 0); | 2157 | failrec->this_mirror, |
2159 | return 0; | 2158 | failrec->bio_flags, 0); |
2159 | return ret; | ||
2160 | } | 2160 | } |
2161 | 2161 | ||
2162 | /* lots and lots of room for performance fixes in the end_bio funcs */ | 2162 | /* lots and lots of room for performance fixes in the end_bio funcs */ |
2163 | 2163 | ||
2164 | int end_extent_writepage(struct page *page, int err, u64 start, u64 end) | ||
2165 | { | ||
2166 | int uptodate = (err == 0); | ||
2167 | struct extent_io_tree *tree; | ||
2168 | int ret; | ||
2169 | |||
2170 | tree = &BTRFS_I(page->mapping->host)->io_tree; | ||
2171 | |||
2172 | if (tree->ops && tree->ops->writepage_end_io_hook) { | ||
2173 | ret = tree->ops->writepage_end_io_hook(page, start, | ||
2174 | end, NULL, uptodate); | ||
2175 | if (ret) | ||
2176 | uptodate = 0; | ||
2177 | } | ||
2178 | |||
2179 | if (!uptodate && tree->ops && | ||
2180 | tree->ops->writepage_io_failed_hook) { | ||
2181 | ret = tree->ops->writepage_io_failed_hook(NULL, page, | ||
2182 | start, end, NULL); | ||
2183 | /* Writeback already completed */ | ||
2184 | if (ret == 0) | ||
2185 | return 1; | ||
2186 | } | ||
2187 | |||
2188 | if (!uptodate) { | ||
2189 | clear_extent_uptodate(tree, start, end, NULL, GFP_NOFS); | ||
2190 | ClearPageUptodate(page); | ||
2191 | SetPageError(page); | ||
2192 | } | ||
2193 | return 0; | ||
2194 | } | ||
2195 | |||
2164 | /* | 2196 | /* |
2165 | * after a writepage IO is done, we need to: | 2197 | * after a writepage IO is done, we need to: |
2166 | * clear the uptodate bits on error | 2198 | * clear the uptodate bits on error |
@@ -2172,13 +2204,11 @@ static int bio_readpage_error(struct bio *failed_bio, struct page *page, | |||
2172 | */ | 2204 | */ |
2173 | static void end_bio_extent_writepage(struct bio *bio, int err) | 2205 | static void end_bio_extent_writepage(struct bio *bio, int err) |
2174 | { | 2206 | { |
2175 | int uptodate = err == 0; | ||
2176 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; | 2207 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; |
2177 | struct extent_io_tree *tree; | 2208 | struct extent_io_tree *tree; |
2178 | u64 start; | 2209 | u64 start; |
2179 | u64 end; | 2210 | u64 end; |
2180 | int whole_page; | 2211 | int whole_page; |
2181 | int ret; | ||
2182 | 2212 | ||
2183 | do { | 2213 | do { |
2184 | struct page *page = bvec->bv_page; | 2214 | struct page *page = bvec->bv_page; |
@@ -2195,28 +2225,9 @@ static void end_bio_extent_writepage(struct bio *bio, int err) | |||
2195 | 2225 | ||
2196 | if (--bvec >= bio->bi_io_vec) | 2226 | if (--bvec >= bio->bi_io_vec) |
2197 | prefetchw(&bvec->bv_page->flags); | 2227 | prefetchw(&bvec->bv_page->flags); |
2198 | if (tree->ops && tree->ops->writepage_end_io_hook) { | ||
2199 | ret = tree->ops->writepage_end_io_hook(page, start, | ||
2200 | end, NULL, uptodate); | ||
2201 | if (ret) | ||
2202 | uptodate = 0; | ||
2203 | } | ||
2204 | |||
2205 | if (!uptodate && tree->ops && | ||
2206 | tree->ops->writepage_io_failed_hook) { | ||
2207 | ret = tree->ops->writepage_io_failed_hook(bio, page, | ||
2208 | start, end, NULL); | ||
2209 | if (ret == 0) { | ||
2210 | uptodate = (err == 0); | ||
2211 | continue; | ||
2212 | } | ||
2213 | } | ||
2214 | 2228 | ||
2215 | if (!uptodate) { | 2229 | if (end_extent_writepage(page, err, start, end)) |
2216 | clear_extent_uptodate(tree, start, end, NULL, GFP_NOFS); | 2230 | continue; |
2217 | ClearPageUptodate(page); | ||
2218 | SetPageError(page); | ||
2219 | } | ||
2220 | 2231 | ||
2221 | if (whole_page) | 2232 | if (whole_page) |
2222 | end_page_writeback(page); | 2233 | end_page_writeback(page); |
@@ -2779,9 +2790,12 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, | |||
2779 | delalloc_start = delalloc_end + 1; | 2790 | delalloc_start = delalloc_end + 1; |
2780 | continue; | 2791 | continue; |
2781 | } | 2792 | } |
2782 | tree->ops->fill_delalloc(inode, page, delalloc_start, | 2793 | ret = tree->ops->fill_delalloc(inode, page, |
2783 | delalloc_end, &page_started, | 2794 | delalloc_start, |
2784 | &nr_written); | 2795 | delalloc_end, |
2796 | &page_started, | ||
2797 | &nr_written); | ||
2798 | BUG_ON(ret); | ||
2785 | /* | 2799 | /* |
2786 | * delalloc_end is already one less than the total | 2800 | * delalloc_end is already one less than the total |
2787 | * length, so we don't subtract one from | 2801 | * length, so we don't subtract one from |
@@ -2818,8 +2832,12 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, | |||
2818 | if (tree->ops && tree->ops->writepage_start_hook) { | 2832 | if (tree->ops && tree->ops->writepage_start_hook) { |
2819 | ret = tree->ops->writepage_start_hook(page, start, | 2833 | ret = tree->ops->writepage_start_hook(page, start, |
2820 | page_end); | 2834 | page_end); |
2821 | if (ret == -EAGAIN) { | 2835 | if (ret) { |
2822 | redirty_page_for_writepage(wbc, page); | 2836 | /* Fixup worker will requeue */ |
2837 | if (ret == -EBUSY) | ||
2838 | wbc->pages_skipped++; | ||
2839 | else | ||
2840 | redirty_page_for_writepage(wbc, page); | ||
2823 | update_nr_written(page, wbc, nr_written); | 2841 | update_nr_written(page, wbc, nr_written); |
2824 | unlock_page(page); | 2842 | unlock_page(page); |
2825 | ret = 0; | 2843 | ret = 0; |
@@ -3289,7 +3307,7 @@ int try_release_extent_mapping(struct extent_map_tree *map, | |||
3289 | len = end - start + 1; | 3307 | len = end - start + 1; |
3290 | write_lock(&map->lock); | 3308 | write_lock(&map->lock); |
3291 | em = lookup_extent_mapping(map, start, len); | 3309 | em = lookup_extent_mapping(map, start, len); |
3292 | if (IS_ERR_OR_NULL(em)) { | 3310 | if (!em) { |
3293 | write_unlock(&map->lock); | 3311 | write_unlock(&map->lock); |
3294 | break; | 3312 | break; |
3295 | } | 3313 | } |
@@ -3853,10 +3871,9 @@ int clear_extent_buffer_uptodate(struct extent_io_tree *tree, | |||
3853 | num_pages = num_extent_pages(eb->start, eb->len); | 3871 | num_pages = num_extent_pages(eb->start, eb->len); |
3854 | clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); | 3872 | clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); |
3855 | 3873 | ||
3856 | if (eb_straddles_pages(eb)) { | 3874 | clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, |
3857 | clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, | 3875 | cached_state, GFP_NOFS); |
3858 | cached_state, GFP_NOFS); | 3876 | |
3859 | } | ||
3860 | for (i = 0; i < num_pages; i++) { | 3877 | for (i = 0; i < num_pages; i++) { |
3861 | page = extent_buffer_page(eb, i); | 3878 | page = extent_buffer_page(eb, i); |
3862 | if (page) | 3879 | if (page) |
@@ -3909,6 +3926,8 @@ int extent_range_uptodate(struct extent_io_tree *tree, | |||
3909 | while (start <= end) { | 3926 | while (start <= end) { |
3910 | index = start >> PAGE_CACHE_SHIFT; | 3927 | index = start >> PAGE_CACHE_SHIFT; |
3911 | page = find_get_page(tree->mapping, index); | 3928 | page = find_get_page(tree->mapping, index); |
3929 | if (!page) | ||
3930 | return 1; | ||
3912 | uptodate = PageUptodate(page); | 3931 | uptodate = PageUptodate(page); |
3913 | page_cache_release(page); | 3932 | page_cache_release(page); |
3914 | if (!uptodate) { | 3933 | if (!uptodate) { |