diff options
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 3c17c9eb0d98..c99121ac5d6b 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -513,7 +513,10 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, | |||
513 | u64 last_end; | 513 | u64 last_end; |
514 | int err; | 514 | int err; |
515 | int set = 0; | 515 | int set = 0; |
516 | int clear = 0; | ||
516 | 517 | ||
518 | if (bits & (EXTENT_IOBITS | EXTENT_BOUNDARY)) | ||
519 | clear = 1; | ||
517 | again: | 520 | again: |
518 | if (!prealloc && (mask & __GFP_WAIT)) { | 521 | if (!prealloc && (mask & __GFP_WAIT)) { |
519 | prealloc = alloc_extent_state(mask); | 522 | prealloc = alloc_extent_state(mask); |
@@ -524,14 +527,20 @@ again: | |||
524 | spin_lock(&tree->lock); | 527 | spin_lock(&tree->lock); |
525 | if (cached_state) { | 528 | if (cached_state) { |
526 | cached = *cached_state; | 529 | cached = *cached_state; |
527 | *cached_state = NULL; | 530 | |
528 | cached_state = NULL; | 531 | if (clear) { |
532 | *cached_state = NULL; | ||
533 | cached_state = NULL; | ||
534 | } | ||
535 | |||
529 | if (cached && cached->tree && cached->start == start) { | 536 | if (cached && cached->tree && cached->start == start) { |
530 | atomic_dec(&cached->refs); | 537 | if (clear) |
538 | atomic_dec(&cached->refs); | ||
531 | state = cached; | 539 | state = cached; |
532 | goto hit_next; | 540 | goto hit_next; |
533 | } | 541 | } |
534 | free_extent_state(cached); | 542 | if (clear) |
543 | free_extent_state(cached); | ||
535 | } | 544 | } |
536 | /* | 545 | /* |
537 | * this search will find the extents that end after | 546 | * this search will find the extents that end after |
@@ -946,11 +955,11 @@ int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, | |||
946 | } | 955 | } |
947 | 956 | ||
948 | int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end, | 957 | int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end, |
949 | gfp_t mask) | 958 | struct extent_state **cached_state, gfp_t mask) |
950 | { | 959 | { |
951 | return set_extent_bit(tree, start, end, | 960 | return set_extent_bit(tree, start, end, |
952 | EXTENT_DELALLOC | EXTENT_DIRTY | EXTENT_UPTODATE, | 961 | EXTENT_DELALLOC | EXTENT_DIRTY | EXTENT_UPTODATE, |
953 | 0, NULL, NULL, mask); | 962 | 0, NULL, cached_state, mask); |
954 | } | 963 | } |
955 | 964 | ||
956 | int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, | 965 | int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, |
@@ -984,10 +993,11 @@ int set_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end, | |||
984 | } | 993 | } |
985 | 994 | ||
986 | static int clear_extent_uptodate(struct extent_io_tree *tree, u64 start, | 995 | static int clear_extent_uptodate(struct extent_io_tree *tree, u64 start, |
987 | u64 end, gfp_t mask) | 996 | u64 end, struct extent_state **cached_state, |
997 | gfp_t mask) | ||
988 | { | 998 | { |
989 | return clear_extent_bit(tree, start, end, EXTENT_UPTODATE, 0, 0, | 999 | return clear_extent_bit(tree, start, end, EXTENT_UPTODATE, 0, 0, |
990 | NULL, mask); | 1000 | cached_state, mask); |
991 | } | 1001 | } |
992 | 1002 | ||
993 | int wait_on_extent_writeback(struct extent_io_tree *tree, u64 start, u64 end) | 1003 | int wait_on_extent_writeback(struct extent_io_tree *tree, u64 start, u64 end) |
@@ -1727,7 +1737,7 @@ static void end_bio_extent_writepage(struct bio *bio, int err) | |||
1727 | } | 1737 | } |
1728 | 1738 | ||
1729 | if (!uptodate) { | 1739 | if (!uptodate) { |
1730 | clear_extent_uptodate(tree, start, end, GFP_NOFS); | 1740 | clear_extent_uptodate(tree, start, end, NULL, GFP_NOFS); |
1731 | ClearPageUptodate(page); | 1741 | ClearPageUptodate(page); |
1732 | SetPageError(page); | 1742 | SetPageError(page); |
1733 | } | 1743 | } |
@@ -2710,6 +2720,7 @@ int extent_readpages(struct extent_io_tree *tree, | |||
2710 | int extent_invalidatepage(struct extent_io_tree *tree, | 2720 | int extent_invalidatepage(struct extent_io_tree *tree, |
2711 | struct page *page, unsigned long offset) | 2721 | struct page *page, unsigned long offset) |
2712 | { | 2722 | { |
2723 | struct extent_state *cached_state = NULL; | ||
2713 | u64 start = ((u64)page->index << PAGE_CACHE_SHIFT); | 2724 | u64 start = ((u64)page->index << PAGE_CACHE_SHIFT); |
2714 | u64 end = start + PAGE_CACHE_SIZE - 1; | 2725 | u64 end = start + PAGE_CACHE_SIZE - 1; |
2715 | size_t blocksize = page->mapping->host->i_sb->s_blocksize; | 2726 | size_t blocksize = page->mapping->host->i_sb->s_blocksize; |
@@ -2718,12 +2729,12 @@ int extent_invalidatepage(struct extent_io_tree *tree, | |||
2718 | if (start > end) | 2729 | if (start > end) |
2719 | return 0; | 2730 | return 0; |
2720 | 2731 | ||
2721 | lock_extent(tree, start, end, GFP_NOFS); | 2732 | lock_extent_bits(tree, start, end, 0, &cached_state, GFP_NOFS); |
2722 | wait_on_page_writeback(page); | 2733 | wait_on_page_writeback(page); |
2723 | clear_extent_bit(tree, start, end, | 2734 | clear_extent_bit(tree, start, end, |
2724 | EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC | | 2735 | EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC | |
2725 | EXTENT_DO_ACCOUNTING, | 2736 | EXTENT_DO_ACCOUNTING, |
2726 | 1, 1, NULL, GFP_NOFS); | 2737 | 1, 1, &cached_state, GFP_NOFS); |
2727 | return 0; | 2738 | return 0; |
2728 | } | 2739 | } |
2729 | 2740 | ||
@@ -2926,16 +2937,17 @@ sector_t extent_bmap(struct address_space *mapping, sector_t iblock, | |||
2926 | get_extent_t *get_extent) | 2937 | get_extent_t *get_extent) |
2927 | { | 2938 | { |
2928 | struct inode *inode = mapping->host; | 2939 | struct inode *inode = mapping->host; |
2940 | struct extent_state *cached_state = NULL; | ||
2929 | u64 start = iblock << inode->i_blkbits; | 2941 | u64 start = iblock << inode->i_blkbits; |
2930 | sector_t sector = 0; | 2942 | sector_t sector = 0; |
2931 | size_t blksize = (1 << inode->i_blkbits); | 2943 | size_t blksize = (1 << inode->i_blkbits); |
2932 | struct extent_map *em; | 2944 | struct extent_map *em; |
2933 | 2945 | ||
2934 | lock_extent(&BTRFS_I(inode)->io_tree, start, start + blksize - 1, | 2946 | lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + blksize - 1, |
2935 | GFP_NOFS); | 2947 | 0, &cached_state, GFP_NOFS); |
2936 | em = get_extent(inode, NULL, 0, start, blksize, 0); | 2948 | em = get_extent(inode, NULL, 0, start, blksize, 0); |
2937 | unlock_extent(&BTRFS_I(inode)->io_tree, start, start + blksize - 1, | 2949 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, start, |
2938 | GFP_NOFS); | 2950 | start + blksize - 1, &cached_state, GFP_NOFS); |
2939 | if (!em || IS_ERR(em)) | 2951 | if (!em || IS_ERR(em)) |
2940 | return 0; | 2952 | return 0; |
2941 | 2953 | ||
@@ -2957,6 +2969,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
2957 | u32 flags = 0; | 2969 | u32 flags = 0; |
2958 | u64 disko = 0; | 2970 | u64 disko = 0; |
2959 | struct extent_map *em = NULL; | 2971 | struct extent_map *em = NULL; |
2972 | struct extent_state *cached_state = NULL; | ||
2960 | int end = 0; | 2973 | int end = 0; |
2961 | u64 em_start = 0, em_len = 0; | 2974 | u64 em_start = 0, em_len = 0; |
2962 | unsigned long emflags; | 2975 | unsigned long emflags; |
@@ -2965,8 +2978,8 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
2965 | if (len == 0) | 2978 | if (len == 0) |
2966 | return -EINVAL; | 2979 | return -EINVAL; |
2967 | 2980 | ||
2968 | lock_extent(&BTRFS_I(inode)->io_tree, start, start + len, | 2981 | lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0, |
2969 | GFP_NOFS); | 2982 | &cached_state, GFP_NOFS); |
2970 | em = get_extent(inode, NULL, 0, off, max - off, 0); | 2983 | em = get_extent(inode, NULL, 0, off, max - off, 0); |
2971 | if (!em) | 2984 | if (!em) |
2972 | goto out; | 2985 | goto out; |
@@ -3029,8 +3042,8 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
3029 | out_free: | 3042 | out_free: |
3030 | free_extent_map(em); | 3043 | free_extent_map(em); |
3031 | out: | 3044 | out: |
3032 | unlock_extent(&BTRFS_I(inode)->io_tree, start, start + len, | 3045 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, start, start + len, |
3033 | GFP_NOFS); | 3046 | &cached_state, GFP_NOFS); |
3034 | return ret; | 3047 | return ret; |
3035 | } | 3048 | } |
3036 | 3049 | ||
@@ -3270,7 +3283,8 @@ int set_extent_buffer_dirty(struct extent_io_tree *tree, | |||
3270 | } | 3283 | } |
3271 | 3284 | ||
3272 | int clear_extent_buffer_uptodate(struct extent_io_tree *tree, | 3285 | int clear_extent_buffer_uptodate(struct extent_io_tree *tree, |
3273 | struct extent_buffer *eb) | 3286 | struct extent_buffer *eb, |
3287 | struct extent_state **cached_state) | ||
3274 | { | 3288 | { |
3275 | unsigned long i; | 3289 | unsigned long i; |
3276 | struct page *page; | 3290 | struct page *page; |
@@ -3280,7 +3294,7 @@ int clear_extent_buffer_uptodate(struct extent_io_tree *tree, | |||
3280 | clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); | 3294 | clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); |
3281 | 3295 | ||
3282 | clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, | 3296 | clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, |
3283 | GFP_NOFS); | 3297 | cached_state, GFP_NOFS); |
3284 | for (i = 0; i < num_pages; i++) { | 3298 | for (i = 0; i < num_pages; i++) { |
3285 | page = extent_buffer_page(eb, i); | 3299 | page = extent_buffer_page(eb, i); |
3286 | if (page) | 3300 | if (page) |
@@ -3340,7 +3354,8 @@ int extent_range_uptodate(struct extent_io_tree *tree, | |||
3340 | } | 3354 | } |
3341 | 3355 | ||
3342 | int extent_buffer_uptodate(struct extent_io_tree *tree, | 3356 | int extent_buffer_uptodate(struct extent_io_tree *tree, |
3343 | struct extent_buffer *eb) | 3357 | struct extent_buffer *eb, |
3358 | struct extent_state *cached_state) | ||
3344 | { | 3359 | { |
3345 | int ret = 0; | 3360 | int ret = 0; |
3346 | unsigned long num_pages; | 3361 | unsigned long num_pages; |
@@ -3352,7 +3367,7 @@ int extent_buffer_uptodate(struct extent_io_tree *tree, | |||
3352 | return 1; | 3367 | return 1; |
3353 | 3368 | ||
3354 | ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1, | 3369 | ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1, |
3355 | EXTENT_UPTODATE, 1, NULL); | 3370 | EXTENT_UPTODATE, 1, cached_state); |
3356 | if (ret) | 3371 | if (ret) |
3357 | return ret; | 3372 | return ret; |
3358 | 3373 | ||