aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent_io.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2009-10-08 13:34:05 -0400
committerChris Mason <chris.mason@oracle.com>2009-10-08 15:21:10 -0400
commit32c00aff718bb54a214b39146bdd9ac01511cd25 (patch)
treec094ee494723a9ebc9d83cb95607f06351665639 /fs/btrfs/extent_io.c
parenta3429ab70b04363c6190964e82f04f44f3e34cf0 (diff)
Btrfs: release delalloc reservations on extent item insertion
This patch fixes an issue with the delalloc metadata space reservation code. The problem is we used to free the reservation as soon as we allocated the delalloc region. The problem with this is if we are not inserting an inline extent, we don't actually insert the extent item until after the ordered extent is written out. This patch does 3 things, 1) It moves the reservation clearing stuff into the ordered code, so when we remove the ordered extent we remove the reservation. 2) It adds a EXTENT_DO_ACCOUNTING flag that gets passed when we clear delalloc bits in the cases where we want to clear the metadata reservation when we clear the delalloc extent, in the case that we do an inline extent or we invalidate the page. 3) It adds another waitqueue to the space info so that when we start a fs wide delalloc flush, anybody else who also hits that area will simply wait for the flush to finish and then try to make their allocation. This has been tested thoroughly to make sure we did not regress on performance. Signed-off-by: Josef Bacik <jbacik@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r--fs/btrfs/extent_io.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index f9708bd01669..96577e8bf9fd 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -460,7 +460,8 @@ static int clear_state_bit(struct extent_io_tree *tree,
460 struct extent_state *state, int bits, int wake, 460 struct extent_state *state, int bits, int wake,
461 int delete) 461 int delete)
462{ 462{
463 int ret = state->state & bits; 463 int bits_to_clear = bits & ~EXTENT_DO_ACCOUNTING;
464 int ret = state->state & bits_to_clear;
464 465
465 if ((bits & EXTENT_DIRTY) && (state->state & EXTENT_DIRTY)) { 466 if ((bits & EXTENT_DIRTY) && (state->state & EXTENT_DIRTY)) {
466 u64 range = state->end - state->start + 1; 467 u64 range = state->end - state->start + 1;
@@ -468,7 +469,7 @@ static int clear_state_bit(struct extent_io_tree *tree,
468 tree->dirty_bytes -= range; 469 tree->dirty_bytes -= range;
469 } 470 }
470 clear_state_cb(tree, state, bits); 471 clear_state_cb(tree, state, bits);
471 state->state &= ~bits; 472 state->state &= ~bits_to_clear;
472 if (wake) 473 if (wake)
473 wake_up(&state->wq); 474 wake_up(&state->wq);
474 if (delete || state->state == 0) { 475 if (delete || state->state == 0) {
@@ -956,7 +957,8 @@ int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
956 gfp_t mask) 957 gfp_t mask)
957{ 958{
958 return clear_extent_bit(tree, start, end, 959 return clear_extent_bit(tree, start, end,
959 EXTENT_DIRTY | EXTENT_DELALLOC, 0, 0, 960 EXTENT_DIRTY | EXTENT_DELALLOC |
961 EXTENT_DO_ACCOUNTING, 0, 0,
960 NULL, mask); 962 NULL, mask);
961} 963}
962 964
@@ -1419,9 +1421,13 @@ int extent_clear_unlock_delalloc(struct inode *inode,
1419 if (op & EXTENT_CLEAR_DELALLOC) 1421 if (op & EXTENT_CLEAR_DELALLOC)
1420 clear_bits |= EXTENT_DELALLOC; 1422 clear_bits |= EXTENT_DELALLOC;
1421 1423
1424 if (op & EXTENT_CLEAR_ACCOUNTING)
1425 clear_bits |= EXTENT_DO_ACCOUNTING;
1426
1422 clear_extent_bit(tree, start, end, clear_bits, 1, 0, NULL, GFP_NOFS); 1427 clear_extent_bit(tree, start, end, clear_bits, 1, 0, NULL, GFP_NOFS);
1423 if (!(op & (EXTENT_CLEAR_UNLOCK_PAGE | EXTENT_CLEAR_DIRTY | EXTENT_SET_WRITEBACK | 1428 if (!(op & (EXTENT_CLEAR_UNLOCK_PAGE | EXTENT_CLEAR_DIRTY |
1424 EXTENT_END_WRITEBACK | EXTENT_SET_PRIVATE2))) 1429 EXTENT_SET_WRITEBACK | EXTENT_END_WRITEBACK |
1430 EXTENT_SET_PRIVATE2)))
1425 return 0; 1431 return 0;
1426 1432
1427 while (nr_pages > 0) { 1433 while (nr_pages > 0) {
@@ -2709,7 +2715,8 @@ int extent_invalidatepage(struct extent_io_tree *tree,
2709 lock_extent(tree, start, end, GFP_NOFS); 2715 lock_extent(tree, start, end, GFP_NOFS);
2710 wait_on_page_writeback(page); 2716 wait_on_page_writeback(page);
2711 clear_extent_bit(tree, start, end, 2717 clear_extent_bit(tree, start, end,
2712 EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC, 2718 EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC |
2719 EXTENT_DO_ACCOUNTING,
2713 1, 1, NULL, GFP_NOFS); 2720 1, 1, NULL, GFP_NOFS);
2714 return 0; 2721 return 0;
2715} 2722}