diff options
author | Chris Mason <chris.mason@oracle.com> | 2011-07-25 06:50:50 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2011-07-27 12:46:47 -0400 |
commit | 19b6caf4acbf065dc96b47741d99f1b87243c468 (patch) | |
tree | 4bce889648c2459e1dbd9fd835a196db26c06f9b /fs | |
parent | 31533fb263928c93a34cda41b66a6e83ade5c766 (diff) |
Btrfs: reduce extent_state lock contention for metadata
For metadata buffers that don't straddle pages (all of them), btrfs
can safely use the page uptodate bits and extent_buffer uptodate bit
instead of needing to use the extent_state tree.
This greatly reduces contention on the state tree lock.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/extent_io.c | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 5392c3b12fc1..7b60f621e761 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -3268,6 +3268,22 @@ int set_extent_buffer_dirty(struct extent_io_tree *tree, | |||
3268 | return was_dirty; | 3268 | return was_dirty; |
3269 | } | 3269 | } |
3270 | 3270 | ||
3271 | static int __eb_straddles_pages(u64 start, u64 len) | ||
3272 | { | ||
3273 | if (len < PAGE_CACHE_SIZE) | ||
3274 | return 1; | ||
3275 | if (start & (PAGE_CACHE_SIZE - 1)) | ||
3276 | return 1; | ||
3277 | if ((start + len) & (PAGE_CACHE_SIZE - 1)) | ||
3278 | return 1; | ||
3279 | return 0; | ||
3280 | } | ||
3281 | |||
3282 | static int eb_straddles_pages(struct extent_buffer *eb) | ||
3283 | { | ||
3284 | return __eb_straddles_pages(eb->start, eb->len); | ||
3285 | } | ||
3286 | |||
3271 | int clear_extent_buffer_uptodate(struct extent_io_tree *tree, | 3287 | int clear_extent_buffer_uptodate(struct extent_io_tree *tree, |
3272 | struct extent_buffer *eb, | 3288 | struct extent_buffer *eb, |
3273 | struct extent_state **cached_state) | 3289 | struct extent_state **cached_state) |
@@ -3279,8 +3295,10 @@ int clear_extent_buffer_uptodate(struct extent_io_tree *tree, | |||
3279 | num_pages = num_extent_pages(eb->start, eb->len); | 3295 | num_pages = num_extent_pages(eb->start, eb->len); |
3280 | clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); | 3296 | clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); |
3281 | 3297 | ||
3282 | clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, | 3298 | if (eb_straddles_pages(eb)) { |
3283 | cached_state, GFP_NOFS); | 3299 | clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, |
3300 | cached_state, GFP_NOFS); | ||
3301 | } | ||
3284 | for (i = 0; i < num_pages; i++) { | 3302 | for (i = 0; i < num_pages; i++) { |
3285 | page = extent_buffer_page(eb, i); | 3303 | page = extent_buffer_page(eb, i); |
3286 | if (page) | 3304 | if (page) |
@@ -3298,8 +3316,10 @@ int set_extent_buffer_uptodate(struct extent_io_tree *tree, | |||
3298 | 3316 | ||
3299 | num_pages = num_extent_pages(eb->start, eb->len); | 3317 | num_pages = num_extent_pages(eb->start, eb->len); |
3300 | 3318 | ||
3301 | set_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, | 3319 | if (eb_straddles_pages(eb)) { |
3302 | NULL, GFP_NOFS); | 3320 | set_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, |
3321 | NULL, GFP_NOFS); | ||
3322 | } | ||
3303 | for (i = 0; i < num_pages; i++) { | 3323 | for (i = 0; i < num_pages; i++) { |
3304 | page = extent_buffer_page(eb, i); | 3324 | page = extent_buffer_page(eb, i); |
3305 | if ((i == 0 && (eb->start & (PAGE_CACHE_SIZE - 1))) || | 3325 | if ((i == 0 && (eb->start & (PAGE_CACHE_SIZE - 1))) || |
@@ -3322,9 +3342,12 @@ int extent_range_uptodate(struct extent_io_tree *tree, | |||
3322 | int uptodate; | 3342 | int uptodate; |
3323 | unsigned long index; | 3343 | unsigned long index; |
3324 | 3344 | ||
3325 | ret = test_range_bit(tree, start, end, EXTENT_UPTODATE, 1, NULL); | 3345 | if (__eb_straddles_pages(start, end - start + 1)) { |
3326 | if (ret) | 3346 | ret = test_range_bit(tree, start, end, |
3327 | return 1; | 3347 | EXTENT_UPTODATE, 1, NULL); |
3348 | if (ret) | ||
3349 | return 1; | ||
3350 | } | ||
3328 | while (start <= end) { | 3351 | while (start <= end) { |
3329 | index = start >> PAGE_CACHE_SHIFT; | 3352 | index = start >> PAGE_CACHE_SHIFT; |
3330 | page = find_get_page(tree->mapping, index); | 3353 | page = find_get_page(tree->mapping, index); |
@@ -3352,10 +3375,12 @@ int extent_buffer_uptodate(struct extent_io_tree *tree, | |||
3352 | if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags)) | 3375 | if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags)) |
3353 | return 1; | 3376 | return 1; |
3354 | 3377 | ||
3355 | ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1, | 3378 | if (eb_straddles_pages(eb)) { |
3356 | EXTENT_UPTODATE, 1, cached_state); | 3379 | ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1, |
3357 | if (ret) | 3380 | EXTENT_UPTODATE, 1, cached_state); |
3358 | return ret; | 3381 | if (ret) |
3382 | return ret; | ||
3383 | } | ||
3359 | 3384 | ||
3360 | num_pages = num_extent_pages(eb->start, eb->len); | 3385 | num_pages = num_extent_pages(eb->start, eb->len); |
3361 | for (i = 0; i < num_pages; i++) { | 3386 | for (i = 0; i < num_pages; i++) { |
@@ -3388,9 +3413,11 @@ int read_extent_buffer_pages(struct extent_io_tree *tree, | |||
3388 | if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags)) | 3413 | if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags)) |
3389 | return 0; | 3414 | return 0; |
3390 | 3415 | ||
3391 | if (test_range_bit(tree, eb->start, eb->start + eb->len - 1, | 3416 | if (eb_straddles_pages(eb)) { |
3392 | EXTENT_UPTODATE, 1, NULL)) { | 3417 | if (test_range_bit(tree, eb->start, eb->start + eb->len - 1, |
3393 | return 0; | 3418 | EXTENT_UPTODATE, 1, NULL)) { |
3419 | return 0; | ||
3420 | } | ||
3394 | } | 3421 | } |
3395 | 3422 | ||
3396 | if (start) { | 3423 | if (start) { |