aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-11-03 22:54:25 -0400
committerChris Mason <chris.mason@oracle.com>2011-11-06 03:04:19 -0500
commit663350ac38c67ca388acea6e876dc6d668c232b0 (patch)
treed111c306c5dfd622c04a0568efde089bdc4577b3
parent6d668dda0caec537fbf28c4d91e6d18181af3cff (diff)
Btrfs: be smarter about committing the transaction in reserve_metadata_bytes
Because of the overcommit stuff I had to make it so that we committed the transaction all the time in reserve_metadata_bytes in case we had overcommitted because of delayed items. This was because previously we had no way of knowing how much space was reserved for delayed items. Now that we have the delayed_block_rsv we can check it to see if committing the transaction would get us anywhere. This patch breaks out the committing logic into a helper function that will check to see if committing the transaction would free enough space for us to get anything done. With this patch xfstests 83 goes from taking 445 seconds to taking 28 seconds on my box. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/extent-tree.c86
1 files changed, 67 insertions, 19 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 01c1f08b976a..5b84205e7685 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3334,12 +3334,12 @@ out:
3334/* 3334/*
3335 * shrink metadata reservation for delalloc 3335 * shrink metadata reservation for delalloc
3336 */ 3336 */
3337static int shrink_delalloc(struct btrfs_trans_handle *trans, 3337static int shrink_delalloc(struct btrfs_root *root, u64 to_reclaim,
3338 struct btrfs_root *root, u64 to_reclaim,
3339 bool wait_ordered) 3338 bool wait_ordered)
3340{ 3339{
3341 struct btrfs_block_rsv *block_rsv; 3340 struct btrfs_block_rsv *block_rsv;
3342 struct btrfs_space_info *space_info; 3341 struct btrfs_space_info *space_info;
3342 struct btrfs_trans_handle *trans;
3343 u64 reserved; 3343 u64 reserved;
3344 u64 max_reclaim; 3344 u64 max_reclaim;
3345 u64 reclaimed = 0; 3345 u64 reclaimed = 0;
@@ -3348,6 +3348,7 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
3348 int loops = 0; 3348 int loops = 0;
3349 unsigned long progress; 3349 unsigned long progress;
3350 3350
3351 trans = (struct btrfs_trans_handle *)current->journal_info;
3351 block_rsv = &root->fs_info->delalloc_block_rsv; 3352 block_rsv = &root->fs_info->delalloc_block_rsv;
3352 space_info = block_rsv->space_info; 3353 space_info = block_rsv->space_info;
3353 3354
@@ -3418,6 +3419,60 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
3418} 3419}
3419 3420
3420/** 3421/**
3422 * maybe_commit_transaction - possibly commit the transaction if its ok to
3423 * @root - the root we're allocating for
3424 * @bytes - the number of bytes we want to reserve
3425 * @force - force the commit
3426 *
3427 * This will check to make sure that committing the transaction will actually
3428 * get us somewhere and then commit the transaction if it does. Otherwise it
3429 * will return -ENOSPC.
3430 */
3431static int may_commit_transaction(struct btrfs_root *root,
3432 struct btrfs_space_info *space_info,
3433 u64 bytes, int force)
3434{
3435 struct btrfs_block_rsv *delayed_rsv = &root->fs_info->delayed_block_rsv;
3436 struct btrfs_trans_handle *trans;
3437
3438 trans = (struct btrfs_trans_handle *)current->journal_info;
3439 if (trans)
3440 return -EAGAIN;
3441
3442 if (force)
3443 goto commit;
3444
3445 /* See if there is enough pinned space to make this reservation */
3446 spin_lock(&space_info->lock);
3447 if (space_info->bytes_pinned >= bytes) {
3448 spin_unlock(&space_info->lock);
3449 goto commit;
3450 }
3451 spin_unlock(&space_info->lock);
3452
3453 /*
3454 * See if there is some space in the delayed insertion reservation for
3455 * this reservation.
3456 */
3457 if (space_info != delayed_rsv->space_info)
3458 return -ENOSPC;
3459
3460 spin_lock(&delayed_rsv->lock);
3461 if (delayed_rsv->size < bytes) {
3462 spin_unlock(&delayed_rsv->lock);
3463 return -ENOSPC;
3464 }
3465 spin_unlock(&delayed_rsv->lock);
3466
3467commit:
3468 trans = btrfs_join_transaction(root);
3469 if (IS_ERR(trans))
3470 return -ENOSPC;
3471
3472 return btrfs_commit_transaction(trans, root);
3473}
3474
3475/**
3421 * reserve_metadata_bytes - try to reserve bytes from the block_rsv's space 3476 * reserve_metadata_bytes - try to reserve bytes from the block_rsv's space
3422 * @root - the root we're allocating for 3477 * @root - the root we're allocating for
3423 * @block_rsv - the block_rsv we're allocating for 3478 * @block_rsv - the block_rsv we're allocating for
@@ -3436,7 +3491,6 @@ static int reserve_metadata_bytes(struct btrfs_root *root,
3436 u64 orig_bytes, int flush) 3491 u64 orig_bytes, int flush)
3437{ 3492{
3438 struct btrfs_space_info *space_info = block_rsv->space_info; 3493 struct btrfs_space_info *space_info = block_rsv->space_info;
3439 struct btrfs_trans_handle *trans;
3440 u64 used; 3494 u64 used;
3441 u64 num_bytes = orig_bytes; 3495 u64 num_bytes = orig_bytes;
3442 int retries = 0; 3496 int retries = 0;
@@ -3445,7 +3499,6 @@ static int reserve_metadata_bytes(struct btrfs_root *root,
3445 bool flushing = false; 3499 bool flushing = false;
3446 bool wait_ordered = false; 3500 bool wait_ordered = false;
3447 3501
3448 trans = (struct btrfs_trans_handle *)current->journal_info;
3449again: 3502again:
3450 ret = 0; 3503 ret = 0;
3451 spin_lock(&space_info->lock); 3504 spin_lock(&space_info->lock);
@@ -3461,7 +3514,7 @@ again:
3461 * deadlock since we are waiting for the flusher to finish, but 3514 * deadlock since we are waiting for the flusher to finish, but
3462 * hold the current transaction open. 3515 * hold the current transaction open.
3463 */ 3516 */
3464 if (trans) 3517 if (current->journal_info)
3465 return -EAGAIN; 3518 return -EAGAIN;
3466 ret = wait_event_interruptible(space_info->wait, 3519 ret = wait_event_interruptible(space_info->wait,
3467 !space_info->flush); 3520 !space_info->flush);
@@ -3517,12 +3570,16 @@ again:
3517 */ 3570 */
3518 avail = (space_info->total_bytes - space_info->bytes_used) * 8; 3571 avail = (space_info->total_bytes - space_info->bytes_used) * 8;
3519 do_div(avail, 10); 3572 do_div(avail, 10);
3520 if (space_info->bytes_pinned >= avail && flush && !trans && 3573 if (space_info->bytes_pinned >= avail && flush && !committed) {
3521 !committed) {
3522 space_info->flush = 1; 3574 space_info->flush = 1;
3523 flushing = true; 3575 flushing = true;
3524 spin_unlock(&space_info->lock); 3576 spin_unlock(&space_info->lock);
3525 goto commit; 3577 ret = may_commit_transaction(root, space_info,
3578 orig_bytes, 1);
3579 if (ret)
3580 goto out;
3581 committed = true;
3582 goto again;
3526 } 3583 }
3527 3584
3528 spin_lock(&root->fs_info->free_chunk_lock); 3585 spin_lock(&root->fs_info->free_chunk_lock);
@@ -3575,7 +3632,7 @@ again:
3575 * We do synchronous shrinking since we don't actually unreserve 3632 * We do synchronous shrinking since we don't actually unreserve
3576 * metadata until after the IO is completed. 3633 * metadata until after the IO is completed.
3577 */ 3634 */
3578 ret = shrink_delalloc(trans, root, num_bytes, wait_ordered); 3635 ret = shrink_delalloc(root, num_bytes, wait_ordered);
3579 if (ret < 0) 3636 if (ret < 0)
3580 goto out; 3637 goto out;
3581 3638
@@ -3592,21 +3649,12 @@ again:
3592 goto again; 3649 goto again;
3593 } 3650 }
3594 3651
3595 ret = -EAGAIN;
3596 if (trans)
3597 goto out;
3598
3599commit:
3600 ret = -ENOSPC; 3652 ret = -ENOSPC;
3601 if (committed) 3653 if (committed)
3602 goto out; 3654 goto out;
3603 3655
3604 trans = btrfs_join_transaction(root); 3656 ret = may_commit_transaction(root, space_info, orig_bytes, 0);
3605 if (IS_ERR(trans))
3606 goto out;
3607 ret = btrfs_commit_transaction(trans, root);
3608 if (!ret) { 3657 if (!ret) {
3609 trans = NULL;
3610 committed = true; 3658 committed = true;
3611 goto again; 3659 goto again;
3612 } 3660 }