diff options
-rw-r--r-- | fs/btrfs/extent_io.c | 85 |
1 files changed, 30 insertions, 55 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 3e6e410002e5..ca4355ddea06 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -1948,28 +1948,6 @@ static void check_page_uptodate(struct extent_io_tree *tree, struct page *page) | |||
1948 | } | 1948 | } |
1949 | 1949 | ||
1950 | /* | 1950 | /* |
1951 | * helper function to unlock a page if all the extents in the tree | ||
1952 | * for that page are unlocked | ||
1953 | */ | ||
1954 | static void check_page_locked(struct extent_io_tree *tree, struct page *page) | ||
1955 | { | ||
1956 | u64 start = page_offset(page); | ||
1957 | u64 end = start + PAGE_CACHE_SIZE - 1; | ||
1958 | if (!test_range_bit(tree, start, end, EXTENT_LOCKED, 0, NULL)) | ||
1959 | unlock_page(page); | ||
1960 | } | ||
1961 | |||
1962 | /* | ||
1963 | * helper function to end page writeback if all the extents | ||
1964 | * in the tree for that page are done with writeback | ||
1965 | */ | ||
1966 | static void check_page_writeback(struct extent_io_tree *tree, | ||
1967 | struct page *page) | ||
1968 | { | ||
1969 | end_page_writeback(page); | ||
1970 | } | ||
1971 | |||
1972 | /* | ||
1973 | * When IO fails, either with EIO or csum verification fails, we | 1951 | * When IO fails, either with EIO or csum verification fails, we |
1974 | * try other mirrors that might have a good copy of the data. This | 1952 | * try other mirrors that might have a good copy of the data. This |
1975 | * io_failure_record is used to record state as we go through all the | 1953 | * io_failure_record is used to record state as we go through all the |
@@ -2398,19 +2376,24 @@ static void end_bio_extent_writepage(struct bio *bio, int err) | |||
2398 | struct extent_io_tree *tree; | 2376 | struct extent_io_tree *tree; |
2399 | u64 start; | 2377 | u64 start; |
2400 | u64 end; | 2378 | u64 end; |
2401 | int whole_page; | ||
2402 | 2379 | ||
2403 | do { | 2380 | do { |
2404 | struct page *page = bvec->bv_page; | 2381 | struct page *page = bvec->bv_page; |
2405 | tree = &BTRFS_I(page->mapping->host)->io_tree; | 2382 | tree = &BTRFS_I(page->mapping->host)->io_tree; |
2406 | 2383 | ||
2407 | start = page_offset(page) + bvec->bv_offset; | 2384 | /* We always issue full-page reads, but if some block |
2408 | end = start + bvec->bv_len - 1; | 2385 | * in a page fails to read, blk_update_request() will |
2386 | * advance bv_offset and adjust bv_len to compensate. | ||
2387 | * Print a warning for nonzero offsets, and an error | ||
2388 | * if they don't add up to a full page. */ | ||
2389 | if (bvec->bv_offset || bvec->bv_len != PAGE_CACHE_SIZE) | ||
2390 | printk("%s page write in btrfs with offset %u and length %u\n", | ||
2391 | bvec->bv_offset + bvec->bv_len != PAGE_CACHE_SIZE | ||
2392 | ? KERN_ERR "partial" : KERN_INFO "incomplete", | ||
2393 | bvec->bv_offset, bvec->bv_len); | ||
2409 | 2394 | ||
2410 | if (bvec->bv_offset == 0 && bvec->bv_len == PAGE_CACHE_SIZE) | 2395 | start = page_offset(page); |
2411 | whole_page = 1; | 2396 | end = start + bvec->bv_offset + bvec->bv_len - 1; |
2412 | else | ||
2413 | whole_page = 0; | ||
2414 | 2397 | ||
2415 | if (--bvec >= bio->bi_io_vec) | 2398 | if (--bvec >= bio->bi_io_vec) |
2416 | prefetchw(&bvec->bv_page->flags); | 2399 | prefetchw(&bvec->bv_page->flags); |
@@ -2418,10 +2401,7 @@ static void end_bio_extent_writepage(struct bio *bio, int err) | |||
2418 | if (end_extent_writepage(page, err, start, end)) | 2401 | if (end_extent_writepage(page, err, start, end)) |
2419 | continue; | 2402 | continue; |
2420 | 2403 | ||
2421 | if (whole_page) | 2404 | end_page_writeback(page); |
2422 | end_page_writeback(page); | ||
2423 | else | ||
2424 | check_page_writeback(tree, page); | ||
2425 | } while (bvec >= bio->bi_io_vec); | 2405 | } while (bvec >= bio->bi_io_vec); |
2426 | 2406 | ||
2427 | bio_put(bio); | 2407 | bio_put(bio); |
@@ -2446,7 +2426,6 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
2446 | struct extent_io_tree *tree; | 2426 | struct extent_io_tree *tree; |
2447 | u64 start; | 2427 | u64 start; |
2448 | u64 end; | 2428 | u64 end; |
2449 | int whole_page; | ||
2450 | int mirror; | 2429 | int mirror; |
2451 | int ret; | 2430 | int ret; |
2452 | 2431 | ||
@@ -2463,13 +2442,19 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
2463 | (long int)bio->bi_bdev); | 2442 | (long int)bio->bi_bdev); |
2464 | tree = &BTRFS_I(page->mapping->host)->io_tree; | 2443 | tree = &BTRFS_I(page->mapping->host)->io_tree; |
2465 | 2444 | ||
2466 | start = page_offset(page) + bvec->bv_offset; | 2445 | /* We always issue full-page reads, but if some block |
2467 | end = start + bvec->bv_len - 1; | 2446 | * in a page fails to read, blk_update_request() will |
2447 | * advance bv_offset and adjust bv_len to compensate. | ||
2448 | * Print a warning for nonzero offsets, and an error | ||
2449 | * if they don't add up to a full page. */ | ||
2450 | if (bvec->bv_offset || bvec->bv_len != PAGE_CACHE_SIZE) | ||
2451 | printk("%s page read in btrfs with offset %u and length %u\n", | ||
2452 | bvec->bv_offset + bvec->bv_len != PAGE_CACHE_SIZE | ||
2453 | ? KERN_ERR "partial" : KERN_INFO "incomplete", | ||
2454 | bvec->bv_offset, bvec->bv_len); | ||
2468 | 2455 | ||
2469 | if (bvec->bv_offset == 0 && bvec->bv_len == PAGE_CACHE_SIZE) | 2456 | start = page_offset(page); |
2470 | whole_page = 1; | 2457 | end = start + bvec->bv_offset + bvec->bv_len - 1; |
2471 | else | ||
2472 | whole_page = 0; | ||
2473 | 2458 | ||
2474 | if (++bvec <= bvec_end) | 2459 | if (++bvec <= bvec_end) |
2475 | prefetchw(&bvec->bv_page->flags); | 2460 | prefetchw(&bvec->bv_page->flags); |
@@ -2528,23 +2513,13 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
2528 | } | 2513 | } |
2529 | unlock_extent_cached(tree, start, end, &cached, GFP_ATOMIC); | 2514 | unlock_extent_cached(tree, start, end, &cached, GFP_ATOMIC); |
2530 | 2515 | ||
2531 | if (whole_page) { | 2516 | if (uptodate) { |
2532 | if (uptodate) { | 2517 | SetPageUptodate(page); |
2533 | SetPageUptodate(page); | ||
2534 | } else { | ||
2535 | ClearPageUptodate(page); | ||
2536 | SetPageError(page); | ||
2537 | } | ||
2538 | unlock_page(page); | ||
2539 | } else { | 2518 | } else { |
2540 | if (uptodate) { | 2519 | ClearPageUptodate(page); |
2541 | check_page_uptodate(tree, page); | 2520 | SetPageError(page); |
2542 | } else { | ||
2543 | ClearPageUptodate(page); | ||
2544 | SetPageError(page); | ||
2545 | } | ||
2546 | check_page_locked(tree, page); | ||
2547 | } | 2521 | } |
2522 | unlock_page(page); | ||
2548 | } while (bvec <= bvec_end); | 2523 | } while (bvec <= bvec_end); |
2549 | 2524 | ||
2550 | bio_put(bio); | 2525 | bio_put(bio); |