diff options
-rw-r--r-- | fs/btrfs/extent-tree.c | 86 |
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 | */ |
3337 | static int shrink_delalloc(struct btrfs_trans_handle *trans, | 3337 | static 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 | */ | ||
3431 | static 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 | |||
3467 | commit: | ||
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; | ||
3449 | again: | 3502 | again: |
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 | |||
3599 | commit: | ||
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 | } |