aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2012-07-02 17:10:51 -0400
committerChris Mason <chris.mason@fusionio.com>2012-07-23 16:27:58 -0400
commitf4c738c2e7bc6d696b0d60155df7ea01684962b6 (patch)
tree920f470a31b8cb371a6b3bb9debd247e919d26df /fs/btrfs/extent-tree.c
parentb9ca0664dc806ba70587f6f3202b60dc736cd6e5 (diff)
Btrfs: rework shrink_delalloc
So shrink_delalloc has grown all sorts of cruft over the years thanks to many reworkings of how we track enospc. What happens now as we fill up the disk is we will loop for freaking ever hoping to reclaim a arbitrary amount of space of metadata, this was from when everybody flushed at the same time. Now we only have people flushing one at a time. So instead of trying to reclaim a huge amount of space, just try to flush a decent chunk of space, and stop looping as soon as we have enough free space to satisfy our reservation. This makes xfstests 224 go much faster. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c81
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 */
3589static int shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, 3589static 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: