diff options
-rw-r--r-- | fs/btrfs/extent_io.c | 46 | ||||
-rw-r--r-- | fs/btrfs/extent_io.h | 2 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 6 | ||||
-rw-r--r-- | fs/btrfs/ordered-data.c | 8 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 2 |
5 files changed, 40 insertions, 24 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 04fafc3cffc0..c9a438d374b6 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -720,6 +720,13 @@ again: | |||
720 | } | 720 | } |
721 | 721 | ||
722 | spin_lock(&tree->lock); | 722 | spin_lock(&tree->lock); |
723 | if (cached_state && *cached_state) { | ||
724 | state = *cached_state; | ||
725 | if (state->start == start && state->tree) { | ||
726 | node = &state->rb_node; | ||
727 | goto hit_next; | ||
728 | } | ||
729 | } | ||
723 | /* | 730 | /* |
724 | * this search will find all the extents that end after | 731 | * this search will find all the extents that end after |
725 | * our range starts. | 732 | * our range starts. |
@@ -1286,6 +1293,7 @@ static noinline u64 find_lock_delalloc_range(struct inode *inode, | |||
1286 | u64 delalloc_start; | 1293 | u64 delalloc_start; |
1287 | u64 delalloc_end; | 1294 | u64 delalloc_end; |
1288 | u64 found; | 1295 | u64 found; |
1296 | struct extent_state *cached_state = NULL; | ||
1289 | int ret; | 1297 | int ret; |
1290 | int loops = 0; | 1298 | int loops = 0; |
1291 | 1299 | ||
@@ -1323,6 +1331,7 @@ again: | |||
1323 | /* some of the pages are gone, lets avoid looping by | 1331 | /* some of the pages are gone, lets avoid looping by |
1324 | * shortening the size of the delalloc range we're searching | 1332 | * shortening the size of the delalloc range we're searching |
1325 | */ | 1333 | */ |
1334 | free_extent_state(cached_state); | ||
1326 | if (!loops) { | 1335 | if (!loops) { |
1327 | unsigned long offset = (*start) & (PAGE_CACHE_SIZE - 1); | 1336 | unsigned long offset = (*start) & (PAGE_CACHE_SIZE - 1); |
1328 | max_bytes = PAGE_CACHE_SIZE - offset; | 1337 | max_bytes = PAGE_CACHE_SIZE - offset; |
@@ -1336,18 +1345,21 @@ again: | |||
1336 | BUG_ON(ret); | 1345 | BUG_ON(ret); |
1337 | 1346 | ||
1338 | /* step three, lock the state bits for the whole range */ | 1347 | /* step three, lock the state bits for the whole range */ |
1339 | lock_extent(tree, delalloc_start, delalloc_end, GFP_NOFS); | 1348 | lock_extent_bits(tree, delalloc_start, delalloc_end, |
1349 | 0, &cached_state, GFP_NOFS); | ||
1340 | 1350 | ||
1341 | /* then test to make sure it is all still delalloc */ | 1351 | /* then test to make sure it is all still delalloc */ |
1342 | ret = test_range_bit(tree, delalloc_start, delalloc_end, | 1352 | ret = test_range_bit(tree, delalloc_start, delalloc_end, |
1343 | EXTENT_DELALLOC, 1); | 1353 | EXTENT_DELALLOC, 1, cached_state); |
1344 | if (!ret) { | 1354 | if (!ret) { |
1345 | unlock_extent(tree, delalloc_start, delalloc_end, GFP_NOFS); | 1355 | unlock_extent_cached(tree, delalloc_start, delalloc_end, |
1356 | &cached_state, GFP_NOFS); | ||
1346 | __unlock_for_delalloc(inode, locked_page, | 1357 | __unlock_for_delalloc(inode, locked_page, |
1347 | delalloc_start, delalloc_end); | 1358 | delalloc_start, delalloc_end); |
1348 | cond_resched(); | 1359 | cond_resched(); |
1349 | goto again; | 1360 | goto again; |
1350 | } | 1361 | } |
1362 | free_extent_state(cached_state); | ||
1351 | *start = delalloc_start; | 1363 | *start = delalloc_start; |
1352 | *end = delalloc_end; | 1364 | *end = delalloc_end; |
1353 | out_failed: | 1365 | out_failed: |
@@ -1530,14 +1542,17 @@ out: | |||
1530 | * range is found set. | 1542 | * range is found set. |
1531 | */ | 1543 | */ |
1532 | int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end, | 1544 | int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end, |
1533 | int bits, int filled) | 1545 | int bits, int filled, struct extent_state *cached) |
1534 | { | 1546 | { |
1535 | struct extent_state *state = NULL; | 1547 | struct extent_state *state = NULL; |
1536 | struct rb_node *node; | 1548 | struct rb_node *node; |
1537 | int bitset = 0; | 1549 | int bitset = 0; |
1538 | 1550 | ||
1539 | spin_lock(&tree->lock); | 1551 | spin_lock(&tree->lock); |
1540 | node = tree_search(tree, start); | 1552 | if (cached && cached->tree && cached->start == start) |
1553 | node = &cached->rb_node; | ||
1554 | else | ||
1555 | node = tree_search(tree, start); | ||
1541 | while (node && start <= end) { | 1556 | while (node && start <= end) { |
1542 | state = rb_entry(node, struct extent_state, rb_node); | 1557 | state = rb_entry(node, struct extent_state, rb_node); |
1543 | 1558 | ||
@@ -1580,7 +1595,7 @@ static int check_page_uptodate(struct extent_io_tree *tree, | |||
1580 | { | 1595 | { |
1581 | u64 start = (u64)page->index << PAGE_CACHE_SHIFT; | 1596 | u64 start = (u64)page->index << PAGE_CACHE_SHIFT; |
1582 | u64 end = start + PAGE_CACHE_SIZE - 1; | 1597 | u64 end = start + PAGE_CACHE_SIZE - 1; |
1583 | if (test_range_bit(tree, start, end, EXTENT_UPTODATE, 1)) | 1598 | if (test_range_bit(tree, start, end, EXTENT_UPTODATE, 1, NULL)) |
1584 | SetPageUptodate(page); | 1599 | SetPageUptodate(page); |
1585 | return 0; | 1600 | return 0; |
1586 | } | 1601 | } |
@@ -1594,7 +1609,7 @@ static int check_page_locked(struct extent_io_tree *tree, | |||
1594 | { | 1609 | { |
1595 | u64 start = (u64)page->index << PAGE_CACHE_SHIFT; | 1610 | u64 start = (u64)page->index << PAGE_CACHE_SHIFT; |
1596 | u64 end = start + PAGE_CACHE_SIZE - 1; | 1611 | u64 end = start + PAGE_CACHE_SIZE - 1; |
1597 | if (!test_range_bit(tree, start, end, EXTENT_LOCKED, 0)) | 1612 | if (!test_range_bit(tree, start, end, EXTENT_LOCKED, 0, NULL)) |
1598 | unlock_page(page); | 1613 | unlock_page(page); |
1599 | return 0; | 1614 | return 0; |
1600 | } | 1615 | } |
@@ -2032,7 +2047,8 @@ static int __extent_read_full_page(struct extent_io_tree *tree, | |||
2032 | continue; | 2047 | continue; |
2033 | } | 2048 | } |
2034 | /* the get_extent function already copied into the page */ | 2049 | /* the get_extent function already copied into the page */ |
2035 | if (test_range_bit(tree, cur, cur_end, EXTENT_UPTODATE, 1)) { | 2050 | if (test_range_bit(tree, cur, cur_end, |
2051 | EXTENT_UPTODATE, 1, NULL)) { | ||
2036 | check_page_uptodate(tree, page); | 2052 | check_page_uptodate(tree, page); |
2037 | unlock_extent(tree, cur, cur + iosize - 1, GFP_NOFS); | 2053 | unlock_extent(tree, cur, cur + iosize - 1, GFP_NOFS); |
2038 | cur = cur + iosize; | 2054 | cur = cur + iosize; |
@@ -2305,7 +2321,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, | |||
2305 | } | 2321 | } |
2306 | /* leave this out until we have a page_mkwrite call */ | 2322 | /* leave this out until we have a page_mkwrite call */ |
2307 | if (0 && !test_range_bit(tree, cur, cur + iosize - 1, | 2323 | if (0 && !test_range_bit(tree, cur, cur + iosize - 1, |
2308 | EXTENT_DIRTY, 0)) { | 2324 | EXTENT_DIRTY, 0, NULL)) { |
2309 | cur = cur + iosize; | 2325 | cur = cur + iosize; |
2310 | pg_offset += iosize; | 2326 | pg_offset += iosize; |
2311 | continue; | 2327 | continue; |
@@ -2721,7 +2737,7 @@ int extent_prepare_write(struct extent_io_tree *tree, | |||
2721 | !isnew && !PageUptodate(page) && | 2737 | !isnew && !PageUptodate(page) && |
2722 | (block_off_end > to || block_off_start < from) && | 2738 | (block_off_end > to || block_off_start < from) && |
2723 | !test_range_bit(tree, block_start, cur_end, | 2739 | !test_range_bit(tree, block_start, cur_end, |
2724 | EXTENT_UPTODATE, 1)) { | 2740 | EXTENT_UPTODATE, 1, NULL)) { |
2725 | u64 sector; | 2741 | u64 sector; |
2726 | u64 extent_offset = block_start - em->start; | 2742 | u64 extent_offset = block_start - em->start; |
2727 | size_t iosize; | 2743 | size_t iosize; |
@@ -2776,7 +2792,7 @@ int try_release_extent_state(struct extent_map_tree *map, | |||
2776 | int ret = 1; | 2792 | int ret = 1; |
2777 | 2793 | ||
2778 | if (test_range_bit(tree, start, end, | 2794 | if (test_range_bit(tree, start, end, |
2779 | EXTENT_IOBITS | EXTENT_ORDERED, 0)) | 2795 | EXTENT_IOBITS | EXTENT_ORDERED, 0, NULL)) |
2780 | ret = 0; | 2796 | ret = 0; |
2781 | else { | 2797 | else { |
2782 | if ((mask & GFP_NOFS) == GFP_NOFS) | 2798 | if ((mask & GFP_NOFS) == GFP_NOFS) |
@@ -2821,7 +2837,7 @@ int try_release_extent_mapping(struct extent_map_tree *map, | |||
2821 | extent_map_end(em) - 1, | 2837 | extent_map_end(em) - 1, |
2822 | EXTENT_LOCKED | EXTENT_WRITEBACK | | 2838 | EXTENT_LOCKED | EXTENT_WRITEBACK | |
2823 | EXTENT_ORDERED, | 2839 | EXTENT_ORDERED, |
2824 | 0)) { | 2840 | 0, NULL)) { |
2825 | remove_extent_mapping(map, em); | 2841 | remove_extent_mapping(map, em); |
2826 | /* once for the rb tree */ | 2842 | /* once for the rb tree */ |
2827 | free_extent_map(em); | 2843 | free_extent_map(em); |
@@ -3237,7 +3253,7 @@ int extent_range_uptodate(struct extent_io_tree *tree, | |||
3237 | int uptodate; | 3253 | int uptodate; |
3238 | unsigned long index; | 3254 | unsigned long index; |
3239 | 3255 | ||
3240 | ret = test_range_bit(tree, start, end, EXTENT_UPTODATE, 1); | 3256 | ret = test_range_bit(tree, start, end, EXTENT_UPTODATE, 1, NULL); |
3241 | if (ret) | 3257 | if (ret) |
3242 | return 1; | 3258 | return 1; |
3243 | while (start <= end) { | 3259 | while (start <= end) { |
@@ -3267,7 +3283,7 @@ int extent_buffer_uptodate(struct extent_io_tree *tree, | |||
3267 | return 1; | 3283 | return 1; |
3268 | 3284 | ||
3269 | ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1, | 3285 | ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1, |
3270 | EXTENT_UPTODATE, 1); | 3286 | EXTENT_UPTODATE, 1, NULL); |
3271 | if (ret) | 3287 | if (ret) |
3272 | return ret; | 3288 | return ret; |
3273 | 3289 | ||
@@ -3303,7 +3319,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree, | |||
3303 | return 0; | 3319 | return 0; |
3304 | 3320 | ||
3305 | if (test_range_bit(tree, eb->start, eb->start + eb->len - 1, | 3321 | if (test_range_bit(tree, eb->start, eb->start + eb->len - 1, |
3306 | EXTENT_UPTODATE, 1)) { | 3322 | EXTENT_UPTODATE, 1, NULL)) { |
3307 | return 0; | 3323 | return 0; |
3308 | } | 3324 | } |
3309 | 3325 | ||
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index c8ead2b8c4c9..09cd6fa3cc86 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -157,7 +157,7 @@ u64 count_range_bits(struct extent_io_tree *tree, | |||
157 | u64 max_bytes, unsigned long bits); | 157 | u64 max_bytes, unsigned long bits); |
158 | 158 | ||
159 | int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end, | 159 | int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end, |
160 | int bits, int filled); | 160 | int bits, int filled, struct extent_state *cached_state); |
161 | int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, | 161 | int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, |
162 | int bits, gfp_t mask); | 162 | int bits, gfp_t mask); |
163 | int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, | 163 | int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index e494545c4202..3f8e93de2989 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1376,7 +1376,7 @@ again: | |||
1376 | 1376 | ||
1377 | /* already ordered? We're done */ | 1377 | /* already ordered? We're done */ |
1378 | if (test_range_bit(&BTRFS_I(inode)->io_tree, page_start, page_end, | 1378 | if (test_range_bit(&BTRFS_I(inode)->io_tree, page_start, page_end, |
1379 | EXTENT_ORDERED, 0)) { | 1379 | EXTENT_ORDERED, 0, NULL)) { |
1380 | goto out; | 1380 | goto out; |
1381 | } | 1381 | } |
1382 | 1382 | ||
@@ -1417,7 +1417,7 @@ static int btrfs_writepage_start_hook(struct page *page, u64 start, u64 end) | |||
1417 | int ret; | 1417 | int ret; |
1418 | 1418 | ||
1419 | ret = test_range_bit(&BTRFS_I(inode)->io_tree, start, end, | 1419 | ret = test_range_bit(&BTRFS_I(inode)->io_tree, start, end, |
1420 | EXTENT_ORDERED, 0); | 1420 | EXTENT_ORDERED, 0, NULL); |
1421 | if (ret) | 1421 | if (ret) |
1422 | return 0; | 1422 | return 0; |
1423 | 1423 | ||
@@ -1795,7 +1795,7 @@ static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end, | |||
1795 | return 0; | 1795 | return 0; |
1796 | 1796 | ||
1797 | if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID && | 1797 | if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID && |
1798 | test_range_bit(io_tree, start, end, EXTENT_NODATASUM, 1)) { | 1798 | test_range_bit(io_tree, start, end, EXTENT_NODATASUM, 1, NULL)) { |
1799 | clear_extent_bits(io_tree, start, end, EXTENT_NODATASUM, | 1799 | clear_extent_bits(io_tree, start, end, EXTENT_NODATASUM, |
1800 | GFP_NOFS); | 1800 | GFP_NOFS); |
1801 | return 0; | 1801 | return 0; |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index d6f0806c682f..7f751e462f0b 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -262,7 +262,7 @@ int btrfs_dec_test_ordered_pending(struct inode *inode, | |||
262 | 262 | ||
263 | ret = test_range_bit(io_tree, entry->file_offset, | 263 | ret = test_range_bit(io_tree, entry->file_offset, |
264 | entry->file_offset + entry->len - 1, | 264 | entry->file_offset + entry->len - 1, |
265 | EXTENT_ORDERED, 0); | 265 | EXTENT_ORDERED, 0, NULL); |
266 | if (ret == 0) | 266 | if (ret == 0) |
267 | ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); | 267 | ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); |
268 | out: | 268 | out: |
@@ -522,7 +522,7 @@ again: | |||
522 | end--; | 522 | end--; |
523 | } | 523 | } |
524 | if (test_range_bit(&BTRFS_I(inode)->io_tree, start, orig_end, | 524 | if (test_range_bit(&BTRFS_I(inode)->io_tree, start, orig_end, |
525 | EXTENT_ORDERED | EXTENT_DELALLOC, 0)) { | 525 | EXTENT_ORDERED | EXTENT_DELALLOC, 0, NULL)) { |
526 | schedule_timeout(1); | 526 | schedule_timeout(1); |
527 | goto again; | 527 | goto again; |
528 | } | 528 | } |
@@ -613,7 +613,7 @@ int btrfs_ordered_update_i_size(struct inode *inode, | |||
613 | */ | 613 | */ |
614 | if (test_range_bit(io_tree, disk_i_size, | 614 | if (test_range_bit(io_tree, disk_i_size, |
615 | ordered->file_offset + ordered->len - 1, | 615 | ordered->file_offset + ordered->len - 1, |
616 | EXTENT_DELALLOC, 0)) { | 616 | EXTENT_DELALLOC, 0, NULL)) { |
617 | goto out; | 617 | goto out; |
618 | } | 618 | } |
619 | /* | 619 | /* |
@@ -664,7 +664,7 @@ int btrfs_ordered_update_i_size(struct inode *inode, | |||
664 | */ | 664 | */ |
665 | if (i_size_test > entry_end(ordered) && | 665 | if (i_size_test > entry_end(ordered) && |
666 | !test_range_bit(io_tree, entry_end(ordered), i_size_test - 1, | 666 | !test_range_bit(io_tree, entry_end(ordered), i_size_test - 1, |
667 | EXTENT_DELALLOC, 0)) { | 667 | EXTENT_DELALLOC, 0, NULL)) { |
668 | new_i_size = min_t(u64, i_size_test, i_size_read(inode)); | 668 | new_i_size = min_t(u64, i_size_test, i_size_read(inode)); |
669 | } | 669 | } |
670 | BTRFS_I(inode)->disk_i_size = new_i_size; | 670 | BTRFS_I(inode)->disk_i_size = new_i_size; |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 4adab903fc2b..3be16ccc7eea 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -2180,7 +2180,7 @@ static int tree_block_processed(u64 bytenr, u32 blocksize, | |||
2180 | struct reloc_control *rc) | 2180 | struct reloc_control *rc) |
2181 | { | 2181 | { |
2182 | if (test_range_bit(&rc->processed_blocks, bytenr, | 2182 | if (test_range_bit(&rc->processed_blocks, bytenr, |
2183 | bytenr + blocksize - 1, EXTENT_DIRTY, 1)) | 2183 | bytenr + blocksize - 1, EXTENT_DIRTY, 1, NULL)) |
2184 | return 1; | 2184 | return 1; |
2185 | return 0; | 2185 | return 0; |
2186 | } | 2186 | } |