aboutsummaryrefslogtreecommitdiffstats
path: root/module/os/freebsd/zfs/abd_os.c
diff options
context:
space:
mode:
authorAlexander Motin <[email protected]>2021-06-16 20:19:34 -0400
committerGitHub <[email protected]>2021-06-16 18:19:34 -0600
commitc4c162c1e8ff9ce8833014711875d18df520096c (patch)
treea056dcb7b82161a9cc2826c70a00998014571e03 /module/os/freebsd/zfs/abd_os.c
parent9ffcaa370aee6871c92c7c84aa65942fba63a884 (diff)
Use wmsum for arc, abd, dbuf and zfetch statistics. (#12172)
wmsum was designed exactly for cases like these with many updates and rare reads. It allows to completely avoid atomic operations on congested global variables. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Mark Maybee <[email protected]> Signed-off-by: Alexander Motin <[email protected]> Sponsored-By: iXsystems, Inc. Closes #12172
Diffstat (limited to 'module/os/freebsd/zfs/abd_os.c')
-rw-r--r--module/os/freebsd/zfs/abd_os.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/module/os/freebsd/zfs/abd_os.c b/module/os/freebsd/zfs/abd_os.c
index 00aa21c6c..47adc2278 100644
--- a/module/os/freebsd/zfs/abd_os.c
+++ b/module/os/freebsd/zfs/abd_os.c
@@ -69,6 +69,15 @@ static abd_stats_t abd_stats = {
{ "linear_data_size", KSTAT_DATA_UINT64 },
};
+struct {
+ wmsum_t abdstat_struct_size;
+ wmsum_t abdstat_scatter_cnt;
+ wmsum_t abdstat_scatter_data_size;
+ wmsum_t abdstat_scatter_chunk_waste;
+ wmsum_t abdstat_linear_cnt;
+ wmsum_t abdstat_linear_data_size;
+} abd_sums;
+
/*
* The size of the chunks ABD allocates. Because the sizes allocated from the
* kmem_cache can't change, this tunable can only be modified at boot. Changing
@@ -271,16 +280,46 @@ abd_free_zero_scatter(void)
kmem_free(abd_zero_buf, zfs_abd_chunk_size);
}
+static int
+abd_kstats_update(kstat_t *ksp, int rw)
+{
+ abd_stats_t *as = ksp->ks_data;
+
+ if (rw == KSTAT_WRITE)
+ return (EACCES);
+ as->abdstat_struct_size.value.ui64 =
+ wmsum_value(&abd_sums.abdstat_struct_size);
+ as->abdstat_scatter_cnt.value.ui64 =
+ wmsum_value(&abd_sums.abdstat_scatter_cnt);
+ as->abdstat_scatter_data_size.value.ui64 =
+ wmsum_value(&abd_sums.abdstat_scatter_data_size);
+ as->abdstat_scatter_chunk_waste.value.ui64 =
+ wmsum_value(&abd_sums.abdstat_scatter_chunk_waste);
+ as->abdstat_linear_cnt.value.ui64 =
+ wmsum_value(&abd_sums.abdstat_linear_cnt);
+ as->abdstat_linear_data_size.value.ui64 =
+ wmsum_value(&abd_sums.abdstat_linear_data_size);
+ return (0);
+}
+
void
abd_init(void)
{
abd_chunk_cache = kmem_cache_create("abd_chunk", zfs_abd_chunk_size, 0,
NULL, NULL, NULL, NULL, 0, KMC_NODEBUG);
+ wmsum_init(&abd_sums.abdstat_struct_size, 0);
+ wmsum_init(&abd_sums.abdstat_scatter_cnt, 0);
+ wmsum_init(&abd_sums.abdstat_scatter_data_size, 0);
+ wmsum_init(&abd_sums.abdstat_scatter_chunk_waste, 0);
+ wmsum_init(&abd_sums.abdstat_linear_cnt, 0);
+ wmsum_init(&abd_sums.abdstat_linear_data_size, 0);
+
abd_ksp = kstat_create("zfs", 0, "abdstats", "misc", KSTAT_TYPE_NAMED,
sizeof (abd_stats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
if (abd_ksp != NULL) {
abd_ksp->ks_data = &abd_stats;
+ abd_ksp->ks_update = abd_kstats_update;
kstat_install(abd_ksp);
}
@@ -297,6 +336,13 @@ abd_fini(void)
abd_ksp = NULL;
}
+ wmsum_fini(&abd_sums.abdstat_struct_size);
+ wmsum_fini(&abd_sums.abdstat_scatter_cnt);
+ wmsum_fini(&abd_sums.abdstat_scatter_data_size);
+ wmsum_fini(&abd_sums.abdstat_scatter_chunk_waste);
+ wmsum_fini(&abd_sums.abdstat_linear_cnt);
+ wmsum_fini(&abd_sums.abdstat_linear_data_size);
+
kmem_cache_destroy(abd_chunk_cache);
abd_chunk_cache = NULL;
}