| From b2cbdc0e07d3bb7962038d3a84f90f34b3ef6ece Mon Sep 17 00:00:00 2001 |
| From: Josef Bacik <josef@toxicpanda.com> |
| Date: Fri, 31 Jan 2020 09:31:05 -0500 |
| Subject: [PATCH] btrfs: do not zero f_bavail if we have available space |
| |
| commit d55966c4279bfc6a0cf0b32bf13f5df228a1eeb6 upstream. |
| |
| There was some logic added a while ago to clear out f_bavail in statfs() |
| if we did not have enough free metadata space to satisfy our global |
| reserve. This was incorrect at the time, however didn't really pose a |
| problem for normal file systems because we would often allocate chunks |
| if we got this low on free metadata space, and thus wouldn't really hit |
| this case unless we were actually full. |
| |
| Fast forward to today and now we are much better about not allocating |
| metadata chunks all of the time. Couple this with d792b0f19711 ("btrfs: |
| always reserve our entire size for the global reserve") which now means |
| we'll easily have a larger global reserve than our free space, we are |
| now more likely to trip over this while still having plenty of space. |
| |
| Fix this by skipping this logic if the global rsv's space_info is not |
| full. space_info->full is 0 unless we've attempted to allocate a chunk |
| for that space_info and that has failed. If this happens then the space |
| for the global reserve is definitely sacred and we need to report |
| b_avail == 0, but before then we can just use our calculated b_avail. |
| |
| Reported-by: Martin Steigerwald <martin@lichtvoll.de> |
| Fixes: ca8a51b3a979 ("btrfs: statfs: report zero available if metadata are exhausted") |
| CC: stable@vger.kernel.org # 4.5+ |
| Reviewed-by: Qu Wenruo <wqu@suse.com> |
| Tested-By: Martin Steigerwald <martin@lichtvoll.de> |
| Signed-off-by: Josef Bacik <josef@toxicpanda.com> |
| Reviewed-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c |
| index 0645ec428b4f..2b2040f14a79 100644 |
| --- a/fs/btrfs/super.c |
| +++ b/fs/btrfs/super.c |
| @@ -2113,7 +2113,15 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
| */ |
| thresh = SZ_4M; |
| |
| - if (!mixed && total_free_meta - thresh < block_rsv->size) |
| + /* |
| + * We only want to claim there's no available space if we can no longer |
| + * allocate chunks for our metadata profile and our global reserve will |
| + * not fit in the free metadata space. If we aren't ->full then we |
| + * still can allocate chunks and thus are fine using the currently |
| + * calculated f_bavail. |
| + */ |
| + if (!mixed && block_rsv->space_info->full && |
| + total_free_meta - thresh < block_rsv->size) |
| buf->f_bavail = 0; |
| |
| buf->f_type = BTRFS_SUPER_MAGIC; |
| -- |
| 2.7.4 |
| |