From 784352fe0bb4814bd969fb390c3d03486a5aaafa Mon Sep 17 00:00:00 2001 From: David Sterba Date: Wed, 21 Aug 2019 18:54:28 +0200 Subject: btrfs: move math functions to misc.h Reviewed-by: Johannes Thumshirn Signed-off-by: David Sterba --- fs/btrfs/block-rsv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/btrfs/block-rsv.c') diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c index 698470b9f32d..ef8b8ae27386 100644 --- a/fs/btrfs/block-rsv.c +++ b/fs/btrfs/block-rsv.c @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 +#include "misc.h" #include "ctree.h" #include "block-rsv.h" #include "space-info.h" -#include "math.h" #include "transaction.h" static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info, -- cgit v1.2.3-59-g8ed1b From f3e75e3805e1da4f7812f731b5396430fa3f2a08 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 22 Aug 2019 15:10:55 -0400 Subject: btrfs: roll tracepoint into btrfs_space_info_update helper We duplicate this tracepoint everywhere we call these helpers, so update the helper to have the tracepoint as well. Signed-off-by: Josef Bacik Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/block-group.c | 3 --- fs/btrfs/block-rsv.c | 5 ----- fs/btrfs/delalloc-space.c | 4 ---- fs/btrfs/extent-tree.c | 9 --------- fs/btrfs/space-info.c | 10 ---------- fs/btrfs/space-info.h | 10 +++++++--- 6 files changed, 7 insertions(+), 34 deletions(-) (limited to 'fs/btrfs/block-rsv.c') diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index 9a09f459337b..d61aa94884f0 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -2696,9 +2696,6 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans, spin_unlock(&cache->lock); spin_unlock(&cache->space_info->lock); - trace_btrfs_space_reservation(info, "pinned", - cache->space_info->flags, - num_bytes, 1); percpu_counter_add_batch( &cache->space_info->total_bytes_pinned, num_bytes, diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c index ef8b8ae27386..c808f93b743a 100644 --- a/fs/btrfs/block-rsv.c +++ b/fs/btrfs/block-rsv.c @@ -283,16 +283,11 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info) block_rsv->reserved += num_bytes; btrfs_space_info_update_bytes_may_use(fs_info, sinfo, num_bytes); - trace_btrfs_space_reservation(fs_info, "space_info", - sinfo->flags, num_bytes, - 1); } } else if (block_rsv->reserved > block_rsv->size) { num_bytes = block_rsv->reserved - block_rsv->size; btrfs_space_info_update_bytes_may_use(fs_info, sinfo, -num_bytes); - trace_btrfs_space_reservation(fs_info, "space_info", - sinfo->flags, num_bytes, 0); block_rsv->reserved = block_rsv->size; } diff --git a/fs/btrfs/delalloc-space.c b/fs/btrfs/delalloc-space.c index 391dcb217098..d949d7d2abed 100644 --- a/fs/btrfs/delalloc-space.c +++ b/fs/btrfs/delalloc-space.c @@ -130,8 +130,6 @@ commit_trans: return -ENOSPC; } btrfs_space_info_update_bytes_may_use(fs_info, data_sinfo, bytes); - trace_btrfs_space_reservation(fs_info, "space_info", - data_sinfo->flags, bytes, 1); spin_unlock(&data_sinfo->lock); return 0; @@ -183,8 +181,6 @@ void btrfs_free_reserved_data_space_noquota(struct inode *inode, u64 start, data_sinfo = fs_info->data_sinfo; spin_lock(&data_sinfo->lock); btrfs_space_info_update_bytes_may_use(fs_info, data_sinfo, -len); - trace_btrfs_space_reservation(fs_info, "space_info", - data_sinfo->flags, len, 0); spin_unlock(&data_sinfo->lock); } diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 2bf5dad82bf1..7d7e91f329ce 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2583,8 +2583,6 @@ static int pin_down_extent(struct btrfs_block_group_cache *cache, spin_unlock(&cache->lock); spin_unlock(&cache->space_info->lock); - trace_btrfs_space_reservation(fs_info, "pinned", - cache->space_info->flags, num_bytes, 1); percpu_counter_add_batch(&cache->space_info->total_bytes_pinned, num_bytes, BTRFS_TOTAL_BYTES_PINNED_BATCH); set_extent_dirty(fs_info->pinned_extents, bytenr, @@ -2842,9 +2840,6 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info, spin_lock(&cache->lock); cache->pinned -= len; btrfs_space_info_update_bytes_pinned(fs_info, space_info, -len); - - trace_btrfs_space_reservation(fs_info, "pinned", - space_info->flags, len, 0); space_info->max_extent_size = 0; percpu_counter_add_batch(&space_info->total_bytes_pinned, -len, BTRFS_TOTAL_BYTES_PINNED_BATCH); @@ -2866,10 +2861,6 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info, space_info, to_add); if (global_rsv->reserved >= global_rsv->size) global_rsv->full = 1; - trace_btrfs_space_reservation(fs_info, - "space_info", - space_info->flags, - to_add, 1); len -= to_add; } spin_unlock(&global_rsv->lock); diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 918bffb6ba30..2aa0b2040ac3 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -279,8 +279,6 @@ again: goto again; } btrfs_space_info_update_bytes_may_use(fs_info, space_info, -num_bytes); - trace_btrfs_space_reservation(fs_info, "space_info", - space_info->flags, num_bytes, 0); spin_unlock(&space_info->lock); } @@ -301,9 +299,6 @@ again: ticket = list_first_entry(head, struct reserve_ticket, list); if (num_bytes >= ticket->bytes) { - trace_btrfs_space_reservation(fs_info, "space_info", - space_info->flags, - ticket->bytes, 1); list_del_init(&ticket->list); num_bytes -= ticket->bytes; btrfs_space_info_update_bytes_may_use(fs_info, @@ -313,9 +308,6 @@ again: space_info->tickets_id++; wake_up(&ticket->wait); } else { - trace_btrfs_space_reservation(fs_info, "space_info", - space_info->flags, - num_bytes, 1); btrfs_space_info_update_bytes_may_use(fs_info, space_info, num_bytes); @@ -1014,8 +1006,6 @@ static int __reserve_metadata_bytes(struct btrfs_fs_info *fs_info, system_chunk))) { btrfs_space_info_update_bytes_may_use(fs_info, space_info, orig_bytes); - trace_btrfs_space_reservation(fs_info, "space_info", - space_info->flags, orig_bytes, 1); ret = 0; } diff --git a/fs/btrfs/space-info.h b/fs/btrfs/space-info.h index c2b54b8e1a14..66d73c290983 100644 --- a/fs/btrfs/space-info.h +++ b/fs/btrfs/space-info.h @@ -87,14 +87,18 @@ static inline bool btrfs_mixed_space_info(struct btrfs_space_info *space_info) * * Declare a helper function to detect underflow of various space info members */ -#define DECLARE_SPACE_INFO_UPDATE(name) \ +#define DECLARE_SPACE_INFO_UPDATE(name, trace_name) \ static inline void \ btrfs_space_info_update_##name(struct btrfs_fs_info *fs_info, \ struct btrfs_space_info *sinfo, \ s64 bytes) \ { \ + const u64 abs_bytes = (bytes < 0) ? -bytes : bytes; \ lockdep_assert_held(&sinfo->lock); \ trace_update_##name(fs_info, sinfo, sinfo->name, bytes); \ + trace_btrfs_space_reservation(fs_info, trace_name, \ + sinfo->flags, abs_bytes, \ + bytes > 0); \ if (bytes < 0 && sinfo->name < -bytes) { \ WARN_ON(1); \ sinfo->name = 0; \ @@ -103,8 +107,8 @@ btrfs_space_info_update_##name(struct btrfs_fs_info *fs_info, \ sinfo->name += bytes; \ } -DECLARE_SPACE_INFO_UPDATE(bytes_may_use); -DECLARE_SPACE_INFO_UPDATE(bytes_pinned); +DECLARE_SPACE_INFO_UPDATE(bytes_may_use, "space_info"); +DECLARE_SPACE_INFO_UPDATE(bytes_pinned, "pinned"); void btrfs_space_info_add_new_bytes(struct btrfs_fs_info *fs_info, struct btrfs_space_info *space_info, -- cgit v1.2.3-59-g8ed1b From d05e46497f86175f85a4f0b9346cae2260e97c8d Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 22 Aug 2019 15:11:02 -0400 Subject: btrfs: rename btrfs_space_info_add_old_bytes This name doesn't really fit with how the space reservation stuff works now, rename it to btrfs_space_info_free_bytes_may_use so it's clear what the function is doing. Reviewed-by: Nikolay Borisov Signed-off-by: Josef Bacik Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/block-rsv.c | 5 +++-- fs/btrfs/delayed-ref.c | 2 +- fs/btrfs/space-info.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'fs/btrfs/block-rsv.c') diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c index c808f93b743a..01b1ce2240bc 100644 --- a/fs/btrfs/block-rsv.c +++ b/fs/btrfs/block-rsv.c @@ -54,8 +54,9 @@ static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info, spin_unlock(&dest->lock); } if (num_bytes) - btrfs_space_info_add_old_bytes(fs_info, space_info, - num_bytes); + btrfs_space_info_free_bytes_may_use(fs_info, + space_info, + num_bytes); } if (qgroup_to_release_ret) *qgroup_to_release_ret = qgroup_to_release; diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c index 951a60c740e7..df3bd880061d 100644 --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c @@ -158,7 +158,7 @@ void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info, trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", 0, num_bytes, 1); if (to_free) - btrfs_space_info_add_old_bytes(fs_info, + btrfs_space_info_free_bytes_may_use(fs_info, delayed_refs_rsv->space_info, to_free); } diff --git a/fs/btrfs/space-info.h b/fs/btrfs/space-info.h index dc6ee66ed600..8867e84aa33d 100644 --- a/fs/btrfs/space-info.h +++ b/fs/btrfs/space-info.h @@ -129,7 +129,7 @@ int btrfs_reserve_metadata_bytes(struct btrfs_root *root, void btrfs_try_granting_tickets(struct btrfs_fs_info *fs_info, struct btrfs_space_info *space_info); -static inline void btrfs_space_info_add_old_bytes( +static inline void btrfs_space_info_free_bytes_may_use( struct btrfs_fs_info *fs_info, struct btrfs_space_info *space_info, u64 num_bytes) -- cgit v1.2.3-59-g8ed1b From 3593ce30b5b4a8fbe84dd1c275e9be01af28511a Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 22 Aug 2019 15:19:00 -0400 Subject: btrfs: change the minimum global reserve size It made sense to have the global reserve set at 16M in the past, but since it is used less nowadays set the minimum size to the number of items we'll need to update the main trees we update during a transaction commit, plus some slop area so we can do unlinks if we need to. In practice this doesn't affect normal file systems, but for xfstests where we do things like fill up a fs and then rm * it can fall over in weird ways. This enables us for more sane behavior at extremely small file system sizes. Signed-off-by: Josef Bacik Signed-off-by: David Sterba --- fs/btrfs/block-rsv.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'fs/btrfs/block-rsv.c') diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c index 01b1ce2240bc..c8b7995c33ee 100644 --- a/fs/btrfs/block-rsv.c +++ b/fs/btrfs/block-rsv.c @@ -259,6 +259,7 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info) struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; struct btrfs_space_info *sinfo = block_rsv->space_info; u64 num_bytes; + unsigned min_items; /* * The global block rsv is based on the size of the extent tree, the @@ -268,7 +269,26 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info) num_bytes = btrfs_root_used(&fs_info->extent_root->root_item) + btrfs_root_used(&fs_info->csum_root->root_item) + btrfs_root_used(&fs_info->tree_root->root_item); - num_bytes = max_t(u64, num_bytes, SZ_16M); + + /* + * We at a minimum are going to modify the csum root, the tree root, and + * the extent root. + */ + min_items = 3; + + /* + * But we also want to reserve enough space so we can do the fallback + * global reserve for an unlink, which is an additional 5 items (see the + * comment in __unlink_start_trans for what we're modifying.) + * + * But we also need space for the delayed ref updates from the unlink, + * so its 10, 5 for the actual operation, and 5 for the delayed ref + * updates. + */ + min_items += 10; + + num_bytes = max_t(u64, num_bytes, + btrfs_calc_insert_metadata_size(fs_info, min_items)); spin_lock(&sinfo->lock); spin_lock(&block_rsv->lock); -- cgit v1.2.3-59-g8ed1b From d792b0f197116b7093c119df29cb174ccfde94b9 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 22 Aug 2019 15:19:01 -0400 Subject: btrfs: always reserve our entire size for the global reserve While messing with the overcommit logic I noticed that sometimes we'd ENOSPC out when really we should have run out of space much earlier. It turns out it's because we'll only reserve up to the free amount left in the space info for the global reserve, but that doesn't make sense with overcommit because we could be well above our actual size. This results in the global reserve not carving out it's entire reservation, and thus not putting enough pressure on the rest of the infrastructure to do the right thing and ENOSPC out at a convenient time. Fix this by always taking our full reservation amount for the global reserve. Reviewed-by: Nikolay Borisov Signed-off-by: Josef Bacik Signed-off-by: David Sterba --- fs/btrfs/block-rsv.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'fs/btrfs/block-rsv.c') diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c index c8b7995c33ee..bea66b499e6f 100644 --- a/fs/btrfs/block-rsv.c +++ b/fs/btrfs/block-rsv.c @@ -296,15 +296,10 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info) block_rsv->size = min_t(u64, num_bytes, SZ_512M); if (block_rsv->reserved < block_rsv->size) { - num_bytes = btrfs_space_info_used(sinfo, true); - if (sinfo->total_bytes > num_bytes) { - num_bytes = sinfo->total_bytes - num_bytes; - num_bytes = min(num_bytes, - block_rsv->size - block_rsv->reserved); - block_rsv->reserved += num_bytes; - btrfs_space_info_update_bytes_may_use(fs_info, sinfo, - num_bytes); - } + num_bytes = block_rsv->size - block_rsv->reserved; + block_rsv->reserved += num_bytes; + btrfs_space_info_update_bytes_may_use(fs_info, sinfo, + num_bytes); } else if (block_rsv->reserved > block_rsv->size) { num_bytes = block_rsv->reserved - block_rsv->size; btrfs_space_info_update_bytes_may_use(fs_info, sinfo, -- cgit v1.2.3-59-g8ed1b From 426551f6866a369c045c77a16725f41a097fac99 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Thu, 22 Aug 2019 15:19:02 -0400 Subject: btrfs: use btrfs_try_granting_tickets in update_global_rsv We have some annoying xfstests tests that will create a very small fs, fill it up, delete it, and repeat to make sure everything works right. This trips btrfs up sometimes because we may commit a transaction to free space, but most of the free metadata space was being reserved by the global reserve. So we commit and update the global reserve, but the space is simply added to bytes_may_use directly, instead of trying to add it to existing tickets. This results in ENOSPC when we really did have space. Fix this by calling btrfs_try_granting_tickets once we add back our excess space to wake any pending tickets. Reviewed-by: Nikolay Borisov Signed-off-by: Josef Bacik Signed-off-by: David Sterba --- fs/btrfs/block-rsv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/btrfs/block-rsv.c') diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c index bea66b499e6f..d07bd41a7c1e 100644 --- a/fs/btrfs/block-rsv.c +++ b/fs/btrfs/block-rsv.c @@ -305,6 +305,7 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info) btrfs_space_info_update_bytes_may_use(fs_info, sinfo, -num_bytes); block_rsv->reserved = block_rsv->size; + btrfs_try_granting_tickets(fs_info, sinfo); } if (block_rsv->reserved == block_rsv->size) -- cgit v1.2.3-59-g8ed1b