diff options
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index dd403b426ff5..2a3624adc0cf 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -1366,7 +1366,7 @@ static int end_bio_extent_writepage(struct bio *bio, | |||
1366 | unsigned int bytes_done, int err) | 1366 | unsigned int bytes_done, int err) |
1367 | #endif | 1367 | #endif |
1368 | { | 1368 | { |
1369 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | 1369 | int uptodate = err == 0; |
1370 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; | 1370 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; |
1371 | struct extent_state *state = bio->bi_private; | 1371 | struct extent_state *state = bio->bi_private; |
1372 | struct extent_io_tree *tree = state->tree; | 1372 | struct extent_io_tree *tree = state->tree; |
@@ -1375,6 +1375,7 @@ static int end_bio_extent_writepage(struct bio *bio, | |||
1375 | u64 end; | 1375 | u64 end; |
1376 | u64 cur; | 1376 | u64 cur; |
1377 | int whole_page; | 1377 | int whole_page; |
1378 | int ret; | ||
1378 | unsigned long flags; | 1379 | unsigned long flags; |
1379 | 1380 | ||
1380 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) | 1381 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) |
@@ -1395,17 +1396,30 @@ static int end_bio_extent_writepage(struct bio *bio, | |||
1395 | if (--bvec >= bio->bi_io_vec) | 1396 | if (--bvec >= bio->bi_io_vec) |
1396 | prefetchw(&bvec->bv_page->flags); | 1397 | prefetchw(&bvec->bv_page->flags); |
1397 | 1398 | ||
1399 | if (tree->ops && tree->ops->writepage_end_io_hook) { | ||
1400 | ret = tree->ops->writepage_end_io_hook(page, start, | ||
1401 | end, state); | ||
1402 | if (ret) | ||
1403 | uptodate = 0; | ||
1404 | } | ||
1405 | |||
1406 | if (!uptodate && tree->ops && | ||
1407 | tree->ops->writepage_io_failed_hook) { | ||
1408 | ret = tree->ops->writepage_io_failed_hook(bio, page, | ||
1409 | start, end, state); | ||
1410 | if (ret == 0) { | ||
1411 | state = NULL; | ||
1412 | uptodate = (err == 0); | ||
1413 | continue; | ||
1414 | } | ||
1415 | } | ||
1416 | |||
1398 | if (!uptodate) { | 1417 | if (!uptodate) { |
1399 | clear_extent_uptodate(tree, start, end, GFP_ATOMIC); | 1418 | clear_extent_uptodate(tree, start, end, GFP_ATOMIC); |
1400 | ClearPageUptodate(page); | 1419 | ClearPageUptodate(page); |
1401 | SetPageError(page); | 1420 | SetPageError(page); |
1402 | } | 1421 | } |
1403 | 1422 | ||
1404 | if (tree->ops && tree->ops->writepage_end_io_hook) { | ||
1405 | tree->ops->writepage_end_io_hook(page, start, end, | ||
1406 | state); | ||
1407 | } | ||
1408 | |||
1409 | /* | 1423 | /* |
1410 | * bios can get merged in funny ways, and so we need to | 1424 | * bios can get merged in funny ways, and so we need to |
1411 | * be careful with the state variable. We know the | 1425 | * be careful with the state variable. We know the |
@@ -2073,9 +2087,9 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, | |||
2073 | } else { | 2087 | } else { |
2074 | ret = 0; | 2088 | ret = 0; |
2075 | } | 2089 | } |
2076 | if (ret) | 2090 | if (ret) { |
2077 | SetPageError(page); | 2091 | SetPageError(page); |
2078 | else { | 2092 | } else { |
2079 | unsigned long max_nr = end_index + 1; | 2093 | unsigned long max_nr = end_index + 1; |
2080 | set_range_writeback(tree, cur, cur + iosize - 1); | 2094 | set_range_writeback(tree, cur, cur + iosize - 1); |
2081 | if (!PageWriteback(page)) { | 2095 | if (!PageWriteback(page)) { |
@@ -2948,6 +2962,25 @@ int set_extent_buffer_dirty(struct extent_io_tree *tree, | |||
2948 | } | 2962 | } |
2949 | EXPORT_SYMBOL(set_extent_buffer_dirty); | 2963 | EXPORT_SYMBOL(set_extent_buffer_dirty); |
2950 | 2964 | ||
2965 | int clear_extent_buffer_uptodate(struct extent_io_tree *tree, | ||
2966 | struct extent_buffer *eb) | ||
2967 | { | ||
2968 | unsigned long i; | ||
2969 | struct page *page; | ||
2970 | unsigned long num_pages; | ||
2971 | |||
2972 | num_pages = num_extent_pages(eb->start, eb->len); | ||
2973 | eb->flags &= ~EXTENT_UPTODATE; | ||
2974 | |||
2975 | clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, | ||
2976 | GFP_NOFS); | ||
2977 | for (i = 0; i < num_pages; i++) { | ||
2978 | page = extent_buffer_page(eb, i); | ||
2979 | ClearPageUptodate(page); | ||
2980 | } | ||
2981 | return 0; | ||
2982 | } | ||
2983 | |||
2951 | int set_extent_buffer_uptodate(struct extent_io_tree *tree, | 2984 | int set_extent_buffer_uptodate(struct extent_io_tree *tree, |
2952 | struct extent_buffer *eb) | 2985 | struct extent_buffer *eb) |
2953 | { | 2986 | { |