---
V2:
Rewrite commit comments.
Add lock_stat test.
Pull dirty_metadata_bytes out to a separate patch.
fs/btrfs/ctree.h | 1 +
fs/btrfs/extent-tree.c | 46
++++++++++++++++++++++++++++--------------
2 files changed, 32 insertions(+), 15 deletions(-)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 118346aceea9..df682a521635 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -422,6 +422,7 @@ struct btrfs_space_info {
* time the transaction commits.
*/
struct percpu_counter total_bytes_pinned;
+ s32 total_bytes_pinned_batch;
struct list_head list;
/* Protected by the spinlock 'lock'. */
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 3d9fe58c0080..937113534ef4 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -758,7 +758,8 @@ static void add_pinned_bytes(struct btrfs_fs_info
*fs_info, s64 num_bytes,
space_info = __find_space_info(fs_info, flags);
ASSERT(space_info);
- percpu_counter_add(&space_info->total_bytes_pinned, num_bytes);
+ percpu_counter_add_batch(&space_info->total_bytes_pinned, num_bytes,
+ space_info->total_bytes_pinned_batch);
}
/*
@@ -2598,8 +2599,9 @@ static int cleanup_ref_head(struct
btrfs_trans_handle *trans,
flags = BTRFS_BLOCK_GROUP_METADATA;
space_info = __find_space_info(fs_info, flags);
ASSERT(space_info);
- percpu_counter_add(&space_info->total_bytes_pinned,
- -head->num_bytes);
+ percpu_counter_add_batch(&space_info->total_bytes_pinned,
+ -head->num_bytes,
+ space_info->total_bytes_pinned_batch);
if (head->is_data) {
spin_lock(&delayed_refs->lock);
@@ -4024,6 +4026,13 @@ static int create_space_info(struct
btrfs_fs_info *info, u64 flags)
kfree(space_info);
return ret;
}
+ /*
+ * Use large batch size to reduce update overhead.
+ * For reader side, we only read it when we are close to ENOSPC and
+ * the read overhead is mostly related to # of cpus, so it is OK to
+ * use arbitrary large value here.
+ */
+ space_info->total_bytes_pinned_batch = SZ_128M;
for (i = 0; i < BTRFS_NR_RAID_TYPES; i++)
INIT_LIST_HEAD(&space_info->block_groups[i]);
@@ -4309,9 +4318,10 @@ int btrfs_alloc_data_chunk_ondemand(struct
btrfs_inode *inode, u64 bytes)
* allocation, and no removed chunk in current transaction,
* don't bother committing the transaction.
*/
- have_pinned_space = percpu_counter_compare(
+ have_pinned_space = __percpu_counter_compare(
&data_sinfo->total_bytes_pinned,
- used + bytes - data_sinfo->total_bytes);
+ used + bytes - data_sinfo->total_bytes,
+ data_sinfo->total_bytes_pinned_batch);
spin_unlock(&data_sinfo->lock);
/* commit the current transaction and try again */
@@ -4912,8 +4922,9 @@ static int may_commit_transaction(struct
btrfs_fs_info *fs_info,
return 0;
/* See if there is enough pinned space to make this reservation */
- if (percpu_counter_compare(&space_info->total_bytes_pinned,
- bytes) >= 0)
+ if (__percpu_counter_compare(&space_info->total_bytes_pinned,
+ bytes,
+ space_info->total_bytes_pinned_batch) >= 0)
goto commit;
/*
@@ -4930,8 +4941,9 @@ static int may_commit_transaction(struct
btrfs_fs_info *fs_info,
bytes -= delayed_rsv->size;
spin_unlock(&delayed_rsv->lock);
- if (percpu_counter_compare(&space_info->total_bytes_pinned,
- bytes) < 0) {
+ if (__percpu_counter_compare(&space_info->total_bytes_pinned,
+ bytes,
+ space_info->total_bytes_pinned_batch) < 0) {
return -ENOSPC;
}
@@ -6268,8 +6280,9 @@ static int update_block_group(struct
btrfs_trans_handle *trans,
trace_btrfs_space_reservation(info, "pinned",
cache->space_info->flags,
num_bytes, 1);
-
percpu_counter_add(&cache->space_info->total_bytes_pinned,
- num_bytes);
+
percpu_counter_add_batch(&cache->space_info->total_bytes_pinned,
+ num_bytes,
+
cache->space_info->total_bytes_pinned_batch);
set_extent_dirty(info->pinned_extents,
bytenr, bytenr + num_bytes - 1,
GFP_NOFS | __GFP_NOFAIL);
@@ -6347,7 +6360,8 @@ static int pin_down_extent(struct btrfs_fs_info
*fs_info,
trace_btrfs_space_reservation(fs_info, "pinned",
cache->space_info->flags, num_bytes, 1);
- percpu_counter_add(&cache->space_info->total_bytes_pinned,
num_bytes);
+ percpu_counter_add_batch(&cache->space_info->total_bytes_pinned,
+ num_bytes, cache->space_info->total_bytes_pinned_batch);
set_extent_dirty(fs_info->pinned_extents, bytenr,
bytenr + num_bytes - 1, GFP_NOFS | __GFP_NOFAIL);
return 0;
@@ -6711,7 +6725,8 @@ static int unpin_extent_range(struct
btrfs_fs_info *fs_info,
trace_btrfs_space_reservation(fs_info, "pinned",
space_info->flags, len, 0);
space_info->max_extent_size = 0;
- percpu_counter_add(&space_info->total_bytes_pinned, -len);
+ percpu_counter_add_batch(&space_info->total_bytes_pinned,
+ -len, space_info->total_bytes_pinned_batch);
if (cache->ro) {
space_info->bytes_readonly += len;
readonly = true;
@@ -10764,8 +10779,9 @@ void btrfs_delete_unused_bgs(struct
btrfs_fs_info *fs_info)
space_info->bytes_pinned -= block_group->pinned;
space_info->bytes_readonly += block_group->pinned;
- percpu_counter_add(&space_info->total_bytes_pinned,
- -block_group->pinned);
+ percpu_counter_add_batch(&space_info->total_bytes_pinned,
+ -block_group->pinned,
+ space_info->total_bytes_pinned_batch);
block_group->pinned = 0;
spin_unlock(&block_group->lock);