aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-09-02 15:22:30 -0400
committerChris Mason <chris.mason@oracle.com>2009-09-11 13:31:07 -0400
commit9655d2982b53fdb38a9e0f2f11315b99b92d66e2 (patch)
treee1271f2f2a3c2c356e0692b36a2d4742b5d651d8 /fs
parentd5550c6315fe0647b7ac21a6a736bf4a42620eac (diff)
Btrfs: use a cached state for extent state operations during delalloc
This changes the btrfs code to find delalloc ranges in the extent state tree to use the new state caching code from set/test bit. It reduces one of the biggest causes of rbtree searches in the writeback path. test_range_bit is also modified to take the cached state as a starting point while searching. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/extent_io.c46
-rw-r--r--fs/btrfs/extent_io.h2
-rw-r--r--fs/btrfs/inode.c6
-rw-r--r--fs/btrfs/ordered-data.c8
-rw-r--r--fs/btrfs/relocation.c2
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;
1353out_failed: 1365out_failed:
@@ -1530,14 +1542,17 @@ out:
1530 * range is found set. 1542 * range is found set.
1531 */ 1543 */
1532int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end, 1544int 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
159int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end, 159int 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);
161int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, 161int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
162 int bits, gfp_t mask); 162 int bits, gfp_t mask);
163int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, 163int 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);
268out: 268out:
@@ -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}