aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-02-06 13:53:19 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-02-20 12:59:32 -0500
commit70afa3998c9baed4186df38988246de1abdab56d (patch)
treef9f773ff12e15d974e55b3836aa0d9d666e80b0f /fs
parent925396ecf251432d6d0f703a6cfd0cb9e651d936 (diff)
Btrfs: rework the overcommit logic to be based on the total size
People have been complaining about random ENOSPC errors that will clear up after a umount or just a given amount of time. Chris was able to reproduce this with stress.sh and lots of processes and so was I. Basically the overcommit stuff would really let us get out of hand, in my tests I saw up to 30 gigs of outstanding reservations with only 2 gigs total of metadata space. This usually worked out fine but with so much outstanding reservation the flushing stuff short circuits to make sure we don't hang forever flushing when we really need ENOSPC. Plus we allocate chunks in order to alleviate the pressure, but this doesn't actually help us since we only use the non-allocated area in our over commit logic. So instead of basing overcommit on the amount of non-allocated space, instead just do it based on how much total space we have, and then limit it to the non-allocated space in case we are short on space to spill over into. This allows us to have the same performance as well as no longer giving random ENOSPC. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/extent-tree.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 3158817cd5a9..81aa7cf3ae86 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3677,6 +3677,7 @@ static int can_overcommit(struct btrfs_root *root,
3677 u64 rsv_size = 0; 3677 u64 rsv_size = 0;
3678 u64 avail; 3678 u64 avail;
3679 u64 used; 3679 u64 used;
3680 u64 to_add;
3680 3681
3681 used = space_info->bytes_used + space_info->bytes_reserved + 3682 used = space_info->bytes_used + space_info->bytes_reserved +
3682 space_info->bytes_pinned + space_info->bytes_readonly; 3683 space_info->bytes_pinned + space_info->bytes_readonly;
@@ -3710,17 +3711,25 @@ static int can_overcommit(struct btrfs_root *root,
3710 BTRFS_BLOCK_GROUP_RAID10)) 3711 BTRFS_BLOCK_GROUP_RAID10))
3711 avail >>= 1; 3712 avail >>= 1;
3712 3713
3714 to_add = space_info->total_bytes;
3715
3713 /* 3716 /*
3714 * If we aren't flushing all things, let us overcommit up to 3717 * If we aren't flushing all things, let us overcommit up to
3715 * 1/2th of the space. If we can flush, don't let us overcommit 3718 * 1/2th of the space. If we can flush, don't let us overcommit
3716 * too much, let it overcommit up to 1/8 of the space. 3719 * too much, let it overcommit up to 1/8 of the space.
3717 */ 3720 */
3718 if (flush == BTRFS_RESERVE_FLUSH_ALL) 3721 if (flush == BTRFS_RESERVE_FLUSH_ALL)
3719 avail >>= 3; 3722 to_add >>= 3;
3720 else 3723 else
3721 avail >>= 1; 3724 to_add >>= 1;
3725
3726 /*
3727 * Limit the overcommit to the amount of free space we could possibly
3728 * allocate for chunks.
3729 */
3730 to_add = min(avail, to_add);
3722 3731
3723 if (used + bytes < space_info->total_bytes + avail) 3732 if (used + bytes < space_info->total_bytes + to_add)
3724 return 1; 3733 return 1;
3725 return 0; 3734 return 0;
3726} 3735}