aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent_io.c
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/btrfs/extent_io.c
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/btrfs/extent_io.c')
-rw-r--r--fs/btrfs/extent_io.c46
1 files changed, 31 insertions, 15 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