diff options
Diffstat (limited to 'fs/btrfs/extent_io.c')
| -rw-r--r-- | fs/btrfs/extent_io.c | 95 |
1 files changed, 51 insertions, 44 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 7073cbb1b2d4..d2d03684fab2 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | #include <linux/slab.h> | 2 | #include <linux/slab.h> |
| 3 | #include <linux/bio.h> | 3 | #include <linux/bio.h> |
| 4 | #include <linux/mm.h> | 4 | #include <linux/mm.h> |
| 5 | #include <linux/gfp.h> | ||
| 6 | #include <linux/pagemap.h> | 5 | #include <linux/pagemap.h> |
| 7 | #include <linux/page-flags.h> | 6 | #include <linux/page-flags.h> |
| 8 | #include <linux/module.h> | 7 | #include <linux/module.h> |
| @@ -513,7 +512,10 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, | |||
| 513 | u64 last_end; | 512 | u64 last_end; |
| 514 | int err; | 513 | int err; |
| 515 | int set = 0; | 514 | int set = 0; |
| 515 | int clear = 0; | ||
| 516 | 516 | ||
| 517 | if (bits & (EXTENT_IOBITS | EXTENT_BOUNDARY)) | ||
| 518 | clear = 1; | ||
| 517 | again: | 519 | again: |
| 518 | if (!prealloc && (mask & __GFP_WAIT)) { | 520 | if (!prealloc && (mask & __GFP_WAIT)) { |
| 519 | prealloc = alloc_extent_state(mask); | 521 | prealloc = alloc_extent_state(mask); |
| @@ -524,14 +526,20 @@ again: | |||
| 524 | spin_lock(&tree->lock); | 526 | spin_lock(&tree->lock); |
| 525 | if (cached_state) { | 527 | if (cached_state) { |
| 526 | cached = *cached_state; | 528 | cached = *cached_state; |
| 527 | *cached_state = NULL; | 529 | |
| 528 | cached_state = NULL; | 530 | if (clear) { |
| 531 | *cached_state = NULL; | ||
| 532 | cached_state = NULL; | ||
| 533 | } | ||
| 534 | |||
| 529 | if (cached && cached->tree && cached->start == start) { | 535 | if (cached && cached->tree && cached->start == start) { |
| 530 | atomic_dec(&cached->refs); | 536 | if (clear) |
| 537 | atomic_dec(&cached->refs); | ||
| 531 | state = cached; | 538 | state = cached; |
| 532 | goto hit_next; | 539 | goto hit_next; |
| 533 | } | 540 | } |
| 534 | free_extent_state(cached); | 541 | if (clear) |
| 542 | free_extent_state(cached); | ||
| 535 | } | 543 | } |
| 536 | /* | 544 | /* |
| 537 | * this search will find the extents that end after | 545 | * this search will find the extents that end after |
| @@ -946,11 +954,11 @@ int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, | |||
| 946 | } | 954 | } |
| 947 | 955 | ||
| 948 | int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end, | 956 | int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end, |
| 949 | gfp_t mask) | 957 | struct extent_state **cached_state, gfp_t mask) |
| 950 | { | 958 | { |
| 951 | return set_extent_bit(tree, start, end, | 959 | return set_extent_bit(tree, start, end, |
| 952 | EXTENT_DELALLOC | EXTENT_DIRTY | EXTENT_UPTODATE, | 960 | EXTENT_DELALLOC | EXTENT_DIRTY | EXTENT_UPTODATE, |
| 953 | 0, NULL, NULL, mask); | 961 | 0, NULL, cached_state, mask); |
| 954 | } | 962 | } |
| 955 | 963 | ||
| 956 | int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, | 964 | int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, |
| @@ -984,10 +992,11 @@ int set_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end, | |||
| 984 | } | 992 | } |
| 985 | 993 | ||
| 986 | static int clear_extent_uptodate(struct extent_io_tree *tree, u64 start, | 994 | static int clear_extent_uptodate(struct extent_io_tree *tree, u64 start, |
| 987 | u64 end, gfp_t mask) | 995 | u64 end, struct extent_state **cached_state, |
| 996 | gfp_t mask) | ||
| 988 | { | 997 | { |
| 989 | return clear_extent_bit(tree, start, end, EXTENT_UPTODATE, 0, 0, | 998 | return clear_extent_bit(tree, start, end, EXTENT_UPTODATE, 0, 0, |
| 990 | NULL, mask); | 999 | cached_state, mask); |
| 991 | } | 1000 | } |
| 992 | 1001 | ||
| 993 | int wait_on_extent_writeback(struct extent_io_tree *tree, u64 start, u64 end) | 1002 | int wait_on_extent_writeback(struct extent_io_tree *tree, u64 start, u64 end) |
| @@ -1171,7 +1180,8 @@ out: | |||
| 1171 | * 1 is returned if we find something, 0 if nothing was in the tree | 1180 | * 1 is returned if we find something, 0 if nothing was in the tree |
| 1172 | */ | 1181 | */ |
| 1173 | static noinline u64 find_delalloc_range(struct extent_io_tree *tree, | 1182 | static noinline u64 find_delalloc_range(struct extent_io_tree *tree, |
| 1174 | u64 *start, u64 *end, u64 max_bytes) | 1183 | u64 *start, u64 *end, u64 max_bytes, |
| 1184 | struct extent_state **cached_state) | ||
| 1175 | { | 1185 | { |
| 1176 | struct rb_node *node; | 1186 | struct rb_node *node; |
| 1177 | struct extent_state *state; | 1187 | struct extent_state *state; |
| @@ -1203,8 +1213,11 @@ static noinline u64 find_delalloc_range(struct extent_io_tree *tree, | |||
| 1203 | *end = state->end; | 1213 | *end = state->end; |
| 1204 | goto out; | 1214 | goto out; |
| 1205 | } | 1215 | } |
| 1206 | if (!found) | 1216 | if (!found) { |
| 1207 | *start = state->start; | 1217 | *start = state->start; |
| 1218 | *cached_state = state; | ||
| 1219 | atomic_inc(&state->refs); | ||
| 1220 | } | ||
| 1208 | found++; | 1221 | found++; |
| 1209 | *end = state->end; | 1222 | *end = state->end; |
| 1210 | cur_start = state->end + 1; | 1223 | cur_start = state->end + 1; |
| @@ -1336,10 +1349,11 @@ again: | |||
| 1336 | delalloc_start = *start; | 1349 | delalloc_start = *start; |
| 1337 | delalloc_end = 0; | 1350 | delalloc_end = 0; |
| 1338 | found = find_delalloc_range(tree, &delalloc_start, &delalloc_end, | 1351 | found = find_delalloc_range(tree, &delalloc_start, &delalloc_end, |
| 1339 | max_bytes); | 1352 | max_bytes, &cached_state); |
| 1340 | if (!found || delalloc_end <= *start) { | 1353 | if (!found || delalloc_end <= *start) { |
| 1341 | *start = delalloc_start; | 1354 | *start = delalloc_start; |
| 1342 | *end = delalloc_end; | 1355 | *end = delalloc_end; |
| 1356 | free_extent_state(cached_state); | ||
| 1343 | return found; | 1357 | return found; |
| 1344 | } | 1358 | } |
| 1345 | 1359 | ||
| @@ -1722,7 +1736,7 @@ static void end_bio_extent_writepage(struct bio *bio, int err) | |||
| 1722 | } | 1736 | } |
| 1723 | 1737 | ||
| 1724 | if (!uptodate) { | 1738 | if (!uptodate) { |
| 1725 | clear_extent_uptodate(tree, start, end, GFP_NOFS); | 1739 | clear_extent_uptodate(tree, start, end, NULL, GFP_NOFS); |
| 1726 | ClearPageUptodate(page); | 1740 | ClearPageUptodate(page); |
| 1727 | SetPageError(page); | 1741 | SetPageError(page); |
| 1728 | } | 1742 | } |
| @@ -1750,7 +1764,8 @@ static void end_bio_extent_writepage(struct bio *bio, int err) | |||
| 1750 | static void end_bio_extent_readpage(struct bio *bio, int err) | 1764 | static void end_bio_extent_readpage(struct bio *bio, int err) |
| 1751 | { | 1765 | { |
| 1752 | int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | 1766 | int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); |
| 1753 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; | 1767 | struct bio_vec *bvec_end = bio->bi_io_vec + bio->bi_vcnt - 1; |
| 1768 | struct bio_vec *bvec = bio->bi_io_vec; | ||
| 1754 | struct extent_io_tree *tree; | 1769 | struct extent_io_tree *tree; |
| 1755 | u64 start; | 1770 | u64 start; |
| 1756 | u64 end; | 1771 | u64 end; |
| @@ -1773,7 +1788,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
| 1773 | else | 1788 | else |
| 1774 | whole_page = 0; | 1789 | whole_page = 0; |
| 1775 | 1790 | ||
| 1776 | if (--bvec >= bio->bi_io_vec) | 1791 | if (++bvec <= bvec_end) |
| 1777 | prefetchw(&bvec->bv_page->flags); | 1792 | prefetchw(&bvec->bv_page->flags); |
| 1778 | 1793 | ||
| 1779 | if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) { | 1794 | if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) { |
| @@ -1818,7 +1833,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
| 1818 | } | 1833 | } |
| 1819 | check_page_locked(tree, page); | 1834 | check_page_locked(tree, page); |
| 1820 | } | 1835 | } |
| 1821 | } while (bvec >= bio->bi_io_vec); | 1836 | } while (bvec <= bvec_end); |
| 1822 | 1837 | ||
| 1823 | bio_put(bio); | 1838 | bio_put(bio); |
| 1824 | } | 1839 | } |
| @@ -2663,33 +2678,20 @@ int extent_readpages(struct extent_io_tree *tree, | |||
| 2663 | { | 2678 | { |
| 2664 | struct bio *bio = NULL; | 2679 | struct bio *bio = NULL; |
| 2665 | unsigned page_idx; | 2680 | unsigned page_idx; |
| 2666 | struct pagevec pvec; | ||
| 2667 | unsigned long bio_flags = 0; | 2681 | unsigned long bio_flags = 0; |
| 2668 | 2682 | ||
| 2669 | pagevec_init(&pvec, 0); | ||
| 2670 | for (page_idx = 0; page_idx < nr_pages; page_idx++) { | 2683 | for (page_idx = 0; page_idx < nr_pages; page_idx++) { |
| 2671 | struct page *page = list_entry(pages->prev, struct page, lru); | 2684 | struct page *page = list_entry(pages->prev, struct page, lru); |
| 2672 | 2685 | ||
| 2673 | prefetchw(&page->flags); | 2686 | prefetchw(&page->flags); |
| 2674 | list_del(&page->lru); | 2687 | list_del(&page->lru); |
| 2675 | /* | 2688 | if (!add_to_page_cache_lru(page, mapping, |
| 2676 | * what we want to do here is call add_to_page_cache_lru, | ||
| 2677 | * but that isn't exported, so we reproduce it here | ||
| 2678 | */ | ||
| 2679 | if (!add_to_page_cache(page, mapping, | ||
| 2680 | page->index, GFP_KERNEL)) { | 2689 | page->index, GFP_KERNEL)) { |
| 2681 | |||
| 2682 | /* open coding of lru_cache_add, also not exported */ | ||
| 2683 | page_cache_get(page); | ||
| 2684 | if (!pagevec_add(&pvec, page)) | ||
| 2685 | __pagevec_lru_add_file(&pvec); | ||
| 2686 | __extent_read_full_page(tree, page, get_extent, | 2690 | __extent_read_full_page(tree, page, get_extent, |
| 2687 | &bio, 0, &bio_flags); | 2691 | &bio, 0, &bio_flags); |
| 2688 | } | 2692 | } |
| 2689 | page_cache_release(page); | 2693 | page_cache_release(page); |
| 2690 | } | 2694 | } |
| 2691 | if (pagevec_count(&pvec)) | ||
| 2692 | __pagevec_lru_add_file(&pvec); | ||
| 2693 | BUG_ON(!list_empty(pages)); | 2695 | BUG_ON(!list_empty(pages)); |
| 2694 | if (bio) | 2696 | if (bio) |
| 2695 | submit_one_bio(READ, bio, 0, bio_flags); | 2697 | submit_one_bio(READ, bio, 0, bio_flags); |
| @@ -2704,6 +2706,7 @@ int extent_readpages(struct extent_io_tree *tree, | |||
| 2704 | int extent_invalidatepage(struct extent_io_tree *tree, | 2706 | int extent_invalidatepage(struct extent_io_tree *tree, |
| 2705 | struct page *page, unsigned long offset) | 2707 | struct page *page, unsigned long offset) |
| 2706 | { | 2708 | { |
| 2709 | struct extent_state *cached_state = NULL; | ||
| 2707 | u64 start = ((u64)page->index << PAGE_CACHE_SHIFT); | 2710 | u64 start = ((u64)page->index << PAGE_CACHE_SHIFT); |
| 2708 | u64 end = start + PAGE_CACHE_SIZE - 1; | 2711 | u64 end = start + PAGE_CACHE_SIZE - 1; |
| 2709 | size_t blocksize = page->mapping->host->i_sb->s_blocksize; | 2712 | size_t blocksize = page->mapping->host->i_sb->s_blocksize; |
| @@ -2712,12 +2715,12 @@ int extent_invalidatepage(struct extent_io_tree *tree, | |||
| 2712 | if (start > end) | 2715 | if (start > end) |
| 2713 | return 0; | 2716 | return 0; |
| 2714 | 2717 | ||
| 2715 | lock_extent(tree, start, end, GFP_NOFS); | 2718 | lock_extent_bits(tree, start, end, 0, &cached_state, GFP_NOFS); |
| 2716 | wait_on_page_writeback(page); | 2719 | wait_on_page_writeback(page); |
| 2717 | clear_extent_bit(tree, start, end, | 2720 | clear_extent_bit(tree, start, end, |
| 2718 | EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC | | 2721 | EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC | |
| 2719 | EXTENT_DO_ACCOUNTING, | 2722 | EXTENT_DO_ACCOUNTING, |
| 2720 | 1, 1, NULL, GFP_NOFS); | 2723 | 1, 1, &cached_state, GFP_NOFS); |
| 2721 | return 0; | 2724 | return 0; |
| 2722 | } | 2725 | } |
| 2723 | 2726 | ||
| @@ -2920,16 +2923,17 @@ sector_t extent_bmap(struct address_space *mapping, sector_t iblock, | |||
| 2920 | get_extent_t *get_extent) | 2923 | get_extent_t *get_extent) |
| 2921 | { | 2924 | { |
| 2922 | struct inode *inode = mapping->host; | 2925 | struct inode *inode = mapping->host; |
| 2926 | struct extent_state *cached_state = NULL; | ||
| 2923 | u64 start = iblock << inode->i_blkbits; | 2927 | u64 start = iblock << inode->i_blkbits; |
| 2924 | sector_t sector = 0; | 2928 | sector_t sector = 0; |
| 2925 | size_t blksize = (1 << inode->i_blkbits); | 2929 | size_t blksize = (1 << inode->i_blkbits); |
| 2926 | struct extent_map *em; | 2930 | struct extent_map *em; |
| 2927 | 2931 | ||
| 2928 | lock_extent(&BTRFS_I(inode)->io_tree, start, start + blksize - 1, | 2932 | lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + blksize - 1, |
| 2929 | GFP_NOFS); | 2933 | 0, &cached_state, GFP_NOFS); |
| 2930 | em = get_extent(inode, NULL, 0, start, blksize, 0); | 2934 | em = get_extent(inode, NULL, 0, start, blksize, 0); |
| 2931 | unlock_extent(&BTRFS_I(inode)->io_tree, start, start + blksize - 1, | 2935 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, start, |
| 2932 | GFP_NOFS); | 2936 | start + blksize - 1, &cached_state, GFP_NOFS); |
| 2933 | if (!em || IS_ERR(em)) | 2937 | if (!em || IS_ERR(em)) |
| 2934 | return 0; | 2938 | return 0; |
| 2935 | 2939 | ||
| @@ -2951,6 +2955,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 2951 | u32 flags = 0; | 2955 | u32 flags = 0; |
| 2952 | u64 disko = 0; | 2956 | u64 disko = 0; |
| 2953 | struct extent_map *em = NULL; | 2957 | struct extent_map *em = NULL; |
| 2958 | struct extent_state *cached_state = NULL; | ||
| 2954 | int end = 0; | 2959 | int end = 0; |
| 2955 | u64 em_start = 0, em_len = 0; | 2960 | u64 em_start = 0, em_len = 0; |
| 2956 | unsigned long emflags; | 2961 | unsigned long emflags; |
| @@ -2959,8 +2964,8 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 2959 | if (len == 0) | 2964 | if (len == 0) |
| 2960 | return -EINVAL; | 2965 | return -EINVAL; |
| 2961 | 2966 | ||
| 2962 | lock_extent(&BTRFS_I(inode)->io_tree, start, start + len, | 2967 | lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0, |
| 2963 | GFP_NOFS); | 2968 | &cached_state, GFP_NOFS); |
| 2964 | em = get_extent(inode, NULL, 0, off, max - off, 0); | 2969 | em = get_extent(inode, NULL, 0, off, max - off, 0); |
| 2965 | if (!em) | 2970 | if (!em) |
| 2966 | goto out; | 2971 | goto out; |
| @@ -3023,8 +3028,8 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 3023 | out_free: | 3028 | out_free: |
| 3024 | free_extent_map(em); | 3029 | free_extent_map(em); |
| 3025 | out: | 3030 | out: |
| 3026 | unlock_extent(&BTRFS_I(inode)->io_tree, start, start + len, | 3031 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, start, start + len, |
| 3027 | GFP_NOFS); | 3032 | &cached_state, GFP_NOFS); |
| 3028 | return ret; | 3033 | return ret; |
| 3029 | } | 3034 | } |
| 3030 | 3035 | ||
| @@ -3264,7 +3269,8 @@ int set_extent_buffer_dirty(struct extent_io_tree *tree, | |||
| 3264 | } | 3269 | } |
| 3265 | 3270 | ||
| 3266 | int clear_extent_buffer_uptodate(struct extent_io_tree *tree, | 3271 | int clear_extent_buffer_uptodate(struct extent_io_tree *tree, |
| 3267 | struct extent_buffer *eb) | 3272 | struct extent_buffer *eb, |
| 3273 | struct extent_state **cached_state) | ||
| 3268 | { | 3274 | { |
| 3269 | unsigned long i; | 3275 | unsigned long i; |
| 3270 | struct page *page; | 3276 | struct page *page; |
| @@ -3274,7 +3280,7 @@ int clear_extent_buffer_uptodate(struct extent_io_tree *tree, | |||
| 3274 | clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); | 3280 | clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); |
| 3275 | 3281 | ||
| 3276 | clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, | 3282 | clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, |
| 3277 | GFP_NOFS); | 3283 | cached_state, GFP_NOFS); |
| 3278 | for (i = 0; i < num_pages; i++) { | 3284 | for (i = 0; i < num_pages; i++) { |
| 3279 | page = extent_buffer_page(eb, i); | 3285 | page = extent_buffer_page(eb, i); |
| 3280 | if (page) | 3286 | if (page) |
| @@ -3334,7 +3340,8 @@ int extent_range_uptodate(struct extent_io_tree *tree, | |||
| 3334 | } | 3340 | } |
| 3335 | 3341 | ||
| 3336 | int extent_buffer_uptodate(struct extent_io_tree *tree, | 3342 | int extent_buffer_uptodate(struct extent_io_tree *tree, |
| 3337 | struct extent_buffer *eb) | 3343 | struct extent_buffer *eb, |
| 3344 | struct extent_state *cached_state) | ||
| 3338 | { | 3345 | { |
| 3339 | int ret = 0; | 3346 | int ret = 0; |
| 3340 | unsigned long num_pages; | 3347 | unsigned long num_pages; |
| @@ -3346,7 +3353,7 @@ int extent_buffer_uptodate(struct extent_io_tree *tree, | |||
| 3346 | return 1; | 3353 | return 1; |
| 3347 | 3354 | ||
| 3348 | ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1, | 3355 | ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1, |
| 3349 | EXTENT_UPTODATE, 1, NULL); | 3356 | EXTENT_UPTODATE, 1, cached_state); |
| 3350 | if (ret) | 3357 | if (ret) |
| 3351 | return ret; | 3358 | return ret; |
| 3352 | 3359 | ||
