Skip to content

Commit

Permalink
Btrfs: do not overcommit if we don't have enough space for global rsv
Browse files Browse the repository at this point in the history
Because of how little we allocate chunks now we can get really tight on
metadata space before we will allocate a new chunk.  This resulted in being
unable to add device extents when allocating a new metadata chunk as we did
not have enough space.  This is because we were allowed to overcommit too
much metadata without actually making sure we had enough space to make
allocations.  The idea behind overcommit is that we are allowed to say "sure
you can have that reservation" when most of the free space is occupied by
reservations, not actual allocations.  But in this case where a majority of
the total space is in use by actual allocations we can screw ourselves by
not being able to make real allocations when it matters.  So make sure we
have enough real space for our global reserve, and if not then don't allow
overcommitting.  Thanks,

Reported-and-tested-by: Jim Schutt <jaschut@sandia.gov>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
  • Loading branch information
Josef Bacik committed Feb 20, 2013
1 parent 0f5d42b commit 96f1bb5
Showing 1 changed file with 19 additions and 2 deletions.
21 changes: 19 additions & 2 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -3672,13 +3672,30 @@ static int can_overcommit(struct btrfs_root *root,
struct btrfs_space_info *space_info, u64 bytes,
enum btrfs_reserve_flush_enum flush)
{
struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv;
u64 profile = btrfs_get_alloc_profile(root, 0);
u64 rsv_size = 0;
u64 avail;
u64 used;

used = space_info->bytes_used + space_info->bytes_reserved +
space_info->bytes_pinned + space_info->bytes_readonly +
space_info->bytes_may_use;
space_info->bytes_pinned + space_info->bytes_readonly;

spin_lock(&global_rsv->lock);
rsv_size = global_rsv->size;
spin_unlock(&global_rsv->lock);

/*
* We only want to allow over committing if we have lots of actual space
* free, but if we don't have enough space to handle the global reserve
* space then we could end up having a real enospc problem when trying
* to allocate a chunk or some other such important allocation.
*/
rsv_size <<= 1;
if (used + rsv_size >= space_info->total_bytes)
return 0;

used += space_info->bytes_may_use;

spin_lock(&root->fs_info->free_chunk_lock);
avail = root->fs_info->free_chunk_space;
Expand Down

0 comments on commit 96f1bb5

Please sign in to comment.