diff options
-rw-r--r-- | fs/btrfs/extent-tree.c | 81 |
1 files changed, 24 insertions, 57 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index ec0328bb86db..5e552f9cc5be 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -3586,89 +3586,58 @@ out: | |||
3586 | /* | 3586 | /* |
3587 | * shrink metadata reservation for delalloc | 3587 | * shrink metadata reservation for delalloc |
3588 | */ | 3588 | */ |
3589 | static int shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, | 3589 | static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig, |
3590 | bool wait_ordered) | 3590 | bool wait_ordered) |
3591 | { | 3591 | { |
3592 | struct btrfs_block_rsv *block_rsv; | 3592 | struct btrfs_block_rsv *block_rsv; |
3593 | struct btrfs_space_info *space_info; | 3593 | struct btrfs_space_info *space_info; |
3594 | struct btrfs_trans_handle *trans; | 3594 | struct btrfs_trans_handle *trans; |
3595 | u64 reserved; | 3595 | u64 delalloc_bytes; |
3596 | u64 max_reclaim; | 3596 | u64 max_reclaim; |
3597 | u64 reclaimed = 0; | ||
3598 | long time_left; | 3597 | long time_left; |
3599 | unsigned long nr_pages = (2 * 1024 * 1024) >> PAGE_CACHE_SHIFT; | 3598 | unsigned long nr_pages = (2 * 1024 * 1024) >> PAGE_CACHE_SHIFT; |
3600 | int loops = 0; | 3599 | int loops = 0; |
3601 | unsigned long progress; | ||
3602 | 3600 | ||
3603 | trans = (struct btrfs_trans_handle *)current->journal_info; | 3601 | trans = (struct btrfs_trans_handle *)current->journal_info; |
3604 | block_rsv = &root->fs_info->delalloc_block_rsv; | 3602 | block_rsv = &root->fs_info->delalloc_block_rsv; |
3605 | space_info = block_rsv->space_info; | 3603 | space_info = block_rsv->space_info; |
3606 | 3604 | ||
3607 | smp_mb(); | 3605 | smp_mb(); |
3608 | reserved = space_info->bytes_may_use; | 3606 | delalloc_bytes = root->fs_info->delalloc_bytes; |
3609 | progress = space_info->reservation_progress; | 3607 | if (delalloc_bytes == 0) { |
3610 | |||
3611 | if (reserved == 0) | ||
3612 | return 0; | ||
3613 | |||
3614 | smp_mb(); | ||
3615 | if (root->fs_info->delalloc_bytes == 0) { | ||
3616 | if (trans) | 3608 | if (trans) |
3617 | return 0; | 3609 | return; |
3618 | btrfs_wait_ordered_extents(root, 0, 0); | 3610 | btrfs_wait_ordered_extents(root, 0, 0); |
3619 | return 0; | 3611 | return; |
3620 | } | 3612 | } |
3621 | 3613 | ||
3622 | max_reclaim = min(reserved, to_reclaim); | 3614 | while (delalloc_bytes && loops < 3) { |
3623 | nr_pages = max_t(unsigned long, nr_pages, | 3615 | max_reclaim = min(delalloc_bytes, to_reclaim); |
3624 | max_reclaim >> PAGE_CACHE_SHIFT); | 3616 | nr_pages = max_reclaim >> PAGE_CACHE_SHIFT; |
3625 | while (loops < 1024) { | ||
3626 | /* have the flusher threads jump in and do some IO */ | ||
3627 | smp_mb(); | ||
3628 | nr_pages = min_t(unsigned long, nr_pages, | ||
3629 | root->fs_info->delalloc_bytes >> PAGE_CACHE_SHIFT); | ||
3630 | writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages, | 3617 | writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages, |
3631 | WB_REASON_FS_FREE_SPACE); | 3618 | WB_REASON_FS_FREE_SPACE); |
3632 | 3619 | ||
3633 | spin_lock(&space_info->lock); | 3620 | spin_lock(&space_info->lock); |
3634 | if (reserved > space_info->bytes_may_use) | 3621 | if (space_info->bytes_used + space_info->bytes_reserved + |
3635 | reclaimed += reserved - space_info->bytes_may_use; | 3622 | space_info->bytes_pinned + space_info->bytes_readonly + |
3636 | reserved = space_info->bytes_may_use; | 3623 | space_info->bytes_may_use + orig <= |
3624 | space_info->total_bytes) { | ||
3625 | spin_unlock(&space_info->lock); | ||
3626 | break; | ||
3627 | } | ||
3637 | spin_unlock(&space_info->lock); | 3628 | spin_unlock(&space_info->lock); |
3638 | 3629 | ||
3639 | loops++; | 3630 | loops++; |
3640 | |||
3641 | if (reserved == 0 || reclaimed >= max_reclaim) | ||
3642 | break; | ||
3643 | |||
3644 | if (trans && trans->transaction->blocked) | ||
3645 | return -EAGAIN; | ||
3646 | |||
3647 | if (wait_ordered && !trans) { | 3631 | if (wait_ordered && !trans) { |
3648 | btrfs_wait_ordered_extents(root, 0, 0); | 3632 | btrfs_wait_ordered_extents(root, 0, 0); |
3649 | } else { | 3633 | } else { |
3650 | time_left = schedule_timeout_interruptible(1); | 3634 | time_left = schedule_timeout_killable(1); |
3651 | |||
3652 | /* We were interrupted, exit */ | ||
3653 | if (time_left) | 3635 | if (time_left) |
3654 | break; | 3636 | break; |
3655 | } | 3637 | } |
3656 | 3638 | smp_mb(); | |
3657 | /* we've kicked the IO a few times, if anything has been freed, | 3639 | delalloc_bytes = root->fs_info->delalloc_bytes; |
3658 | * exit. There is no sense in looping here for a long time | ||
3659 | * when we really need to commit the transaction, or there are | ||
3660 | * just too many writers without enough free space | ||
3661 | */ | ||
3662 | |||
3663 | if (loops > 3) { | ||
3664 | smp_mb(); | ||
3665 | if (progress != space_info->reservation_progress) | ||
3666 | break; | ||
3667 | } | ||
3668 | |||
3669 | } | 3640 | } |
3670 | |||
3671 | return reclaimed >= to_reclaim; | ||
3672 | } | 3641 | } |
3673 | 3642 | ||
3674 | /** | 3643 | /** |
@@ -3742,15 +3711,13 @@ static int flush_space(struct btrfs_root *root, | |||
3742 | { | 3711 | { |
3743 | struct btrfs_trans_handle *trans; | 3712 | struct btrfs_trans_handle *trans; |
3744 | int nr; | 3713 | int nr; |
3745 | int ret; | 3714 | int ret = 0; |
3746 | 3715 | ||
3747 | switch (state) { | 3716 | switch (state) { |
3748 | case FLUSH_DELALLOC: | 3717 | case FLUSH_DELALLOC: |
3749 | case FLUSH_DELALLOC_WAIT: | 3718 | case FLUSH_DELALLOC_WAIT: |
3750 | ret = shrink_delalloc(root, num_bytes, | 3719 | shrink_delalloc(root, num_bytes, orig_bytes, |
3751 | state == FLUSH_DELALLOC_WAIT); | 3720 | state == FLUSH_DELALLOC_WAIT); |
3752 | if (ret > 0) | ||
3753 | ret = 0; | ||
3754 | break; | 3721 | break; |
3755 | case FLUSH_DELAYED_ITEMS_NR: | 3722 | case FLUSH_DELAYED_ITEMS_NR: |
3756 | case FLUSH_DELAYED_ITEMS: | 3723 | case FLUSH_DELAYED_ITEMS: |