Path: blob/main/sys/contrib/openzfs/module/zfs/dataset_kstats.c
48383 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* Common Development and Distribution License (the "License").6* You may not use this file except in compliance with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/2122/*23* Copyright (c) 2018 by Delphix. All rights reserved.24* Copyright (c) 2018 Datto Inc.25*/2627#include <sys/dataset_kstats.h>28#include <sys/dmu_objset.h>29#include <sys/dsl_dataset.h>30#include <sys/spa.h>3132static dataset_kstat_values_t empty_dataset_kstats = {33{ "dataset_name", KSTAT_DATA_STRING },34{ "writes", KSTAT_DATA_UINT64 },35{ "nwritten", KSTAT_DATA_UINT64 },36{ "reads", KSTAT_DATA_UINT64 },37{ "nread", KSTAT_DATA_UINT64 },38{ "nunlinks", KSTAT_DATA_UINT64 },39{ "nunlinked", KSTAT_DATA_UINT64 },40{41{ "zil_commit_count", KSTAT_DATA_UINT64 },42{ "zil_commit_writer_count", KSTAT_DATA_UINT64 },43{ "zil_commit_error_count", KSTAT_DATA_UINT64 },44{ "zil_commit_stall_count", KSTAT_DATA_UINT64 },45{ "zil_commit_suspend_count", KSTAT_DATA_UINT64 },46{ "zil_commit_crash_count", KSTAT_DATA_UINT64 },47{ "zil_itx_count", KSTAT_DATA_UINT64 },48{ "zil_itx_indirect_count", KSTAT_DATA_UINT64 },49{ "zil_itx_indirect_bytes", KSTAT_DATA_UINT64 },50{ "zil_itx_copied_count", KSTAT_DATA_UINT64 },51{ "zil_itx_copied_bytes", KSTAT_DATA_UINT64 },52{ "zil_itx_needcopy_count", KSTAT_DATA_UINT64 },53{ "zil_itx_needcopy_bytes", KSTAT_DATA_UINT64 },54{ "zil_itx_metaslab_normal_count", KSTAT_DATA_UINT64 },55{ "zil_itx_metaslab_normal_bytes", KSTAT_DATA_UINT64 },56{ "zil_itx_metaslab_normal_write", KSTAT_DATA_UINT64 },57{ "zil_itx_metaslab_normal_alloc", KSTAT_DATA_UINT64 },58{ "zil_itx_metaslab_slog_count", KSTAT_DATA_UINT64 },59{ "zil_itx_metaslab_slog_bytes", KSTAT_DATA_UINT64 },60{ "zil_itx_metaslab_slog_write", KSTAT_DATA_UINT64 },61{ "zil_itx_metaslab_slog_alloc", KSTAT_DATA_UINT64 }62}63};6465static int66dataset_kstats_update(kstat_t *ksp, int rw)67{68dataset_kstats_t *dk = ksp->ks_private;69dataset_kstat_values_t *dkv = ksp->ks_data;70ASSERT3P(dk->dk_kstats->ks_data, ==, dkv);7172if (rw == KSTAT_WRITE)73return (EACCES);7475dkv->dkv_writes.value.ui64 =76wmsum_value(&dk->dk_sums.dss_writes);77dkv->dkv_nwritten.value.ui64 =78wmsum_value(&dk->dk_sums.dss_nwritten);79dkv->dkv_reads.value.ui64 =80wmsum_value(&dk->dk_sums.dss_reads);81dkv->dkv_nread.value.ui64 =82wmsum_value(&dk->dk_sums.dss_nread);83dkv->dkv_nunlinks.value.ui64 =84wmsum_value(&dk->dk_sums.dss_nunlinks);85dkv->dkv_nunlinked.value.ui64 =86wmsum_value(&dk->dk_sums.dss_nunlinked);8788zil_kstat_values_update(&dkv->dkv_zil_stats, &dk->dk_zil_sums);8990return (0);91}9293int94dataset_kstats_create(dataset_kstats_t *dk, objset_t *objset)95{96/*97* There should not be anything wrong with having kstats for98* snapshots. Since we are not sure how useful they would be99* though nor how much their memory overhead would matter in100* a filesystem with many snapshots, we skip them for now.101*/102if (dmu_objset_is_snapshot(objset))103return (0);104105/*106* At the time of this writing, KSTAT_STRLEN is 255 in Linux,107* and the spa_name can theoretically be up to 256 characters.108* In reality though the spa_name can be 240 characters max109* [see origin directory name check in pool_namecheck()]. Thus,110* the naming scheme for the module name below should not cause111* any truncations. In the event that a truncation does happen112* though, due to some future change, we silently skip creating113* the kstat and log the event.114*/115char kstat_module_name[KSTAT_STRLEN];116int n = snprintf(kstat_module_name, sizeof (kstat_module_name),117"zfs/%s", spa_name(dmu_objset_spa(objset)));118if (n < 0) {119zfs_dbgmsg("failed to create dataset kstat for objset %lld: "120" snprintf() for kstat module name returned %d",121(unsigned long long)dmu_objset_id(objset), n);122return (SET_ERROR(EINVAL));123} else if (n >= KSTAT_STRLEN) {124zfs_dbgmsg("failed to create dataset kstat for objset %lld: "125"kstat module name length (%d) exceeds limit (%d)",126(unsigned long long)dmu_objset_id(objset),127n, KSTAT_STRLEN);128return (SET_ERROR(ENAMETOOLONG));129}130131char kstat_name[KSTAT_STRLEN];132n = snprintf(kstat_name, sizeof (kstat_name), "objset-0x%llx",133(unsigned long long)dmu_objset_id(objset));134if (n < 0) {135zfs_dbgmsg("failed to create dataset kstat for objset %lld: "136" snprintf() for kstat name returned %d",137(unsigned long long)dmu_objset_id(objset), n);138return (SET_ERROR(EINVAL));139} else if (n >= KSTAT_STRLEN) {140zfs_dbgmsg("failed to create dataset kstat for objset %lld: "141"kstat name length (%d) exceeds limit (%d)",142(unsigned long long)dmu_objset_id(objset),143n, KSTAT_STRLEN);144return (SET_ERROR(ENAMETOOLONG));145}146147kstat_t *kstat = kstat_create(kstat_module_name, 0, kstat_name,148"dataset", KSTAT_TYPE_NAMED,149sizeof (empty_dataset_kstats) / sizeof (kstat_named_t),150KSTAT_FLAG_VIRTUAL);151if (kstat == NULL)152return (SET_ERROR(ENOMEM));153154dataset_kstat_values_t *dk_kstats =155kmem_alloc(sizeof (empty_dataset_kstats), KM_SLEEP);156memcpy(dk_kstats, &empty_dataset_kstats,157sizeof (empty_dataset_kstats));158159char *ds_name = kmem_zalloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);160dsl_dataset_name(objset->os_dsl_dataset, ds_name);161KSTAT_NAMED_STR_PTR(&dk_kstats->dkv_ds_name) = ds_name;162KSTAT_NAMED_STR_BUFLEN(&dk_kstats->dkv_ds_name) =163ZFS_MAX_DATASET_NAME_LEN;164165kstat->ks_data = dk_kstats;166kstat->ks_update = dataset_kstats_update;167kstat->ks_private = dk;168kstat->ks_data_size += ZFS_MAX_DATASET_NAME_LEN;169170wmsum_init(&dk->dk_sums.dss_writes, 0);171wmsum_init(&dk->dk_sums.dss_nwritten, 0);172wmsum_init(&dk->dk_sums.dss_reads, 0);173wmsum_init(&dk->dk_sums.dss_nread, 0);174wmsum_init(&dk->dk_sums.dss_nunlinks, 0);175wmsum_init(&dk->dk_sums.dss_nunlinked, 0);176zil_sums_init(&dk->dk_zil_sums);177178dk->dk_kstats = kstat;179kstat_install(kstat);180return (0);181}182183void184dataset_kstats_destroy(dataset_kstats_t *dk)185{186if (dk->dk_kstats == NULL)187return;188189dataset_kstat_values_t *dkv = dk->dk_kstats->ks_data;190kstat_delete(dk->dk_kstats);191dk->dk_kstats = NULL;192kmem_free(KSTAT_NAMED_STR_PTR(&dkv->dkv_ds_name),193KSTAT_NAMED_STR_BUFLEN(&dkv->dkv_ds_name));194kmem_free(dkv, sizeof (empty_dataset_kstats));195196wmsum_fini(&dk->dk_sums.dss_writes);197wmsum_fini(&dk->dk_sums.dss_nwritten);198wmsum_fini(&dk->dk_sums.dss_reads);199wmsum_fini(&dk->dk_sums.dss_nread);200wmsum_fini(&dk->dk_sums.dss_nunlinks);201wmsum_fini(&dk->dk_sums.dss_nunlinked);202zil_sums_fini(&dk->dk_zil_sums);203}204205void206dataset_kstats_rename(dataset_kstats_t *dk, const char *name)207{208if (dk->dk_kstats == NULL)209return;210211dataset_kstat_values_t *dkv = dk->dk_kstats->ks_data;212char *ds_name;213214ds_name = KSTAT_NAMED_STR_PTR(&dkv->dkv_ds_name);215ASSERT3S(ds_name, !=, NULL);216(void) strlcpy(ds_name, name,217KSTAT_NAMED_STR_BUFLEN(&dkv->dkv_ds_name));218}219220void221dataset_kstats_update_write_kstats(dataset_kstats_t *dk, int64_t nwritten)222{223ASSERT3S(nwritten, >=, 0);224225if (dk->dk_kstats == NULL)226return;227228wmsum_add(&dk->dk_sums.dss_writes, 1);229wmsum_add(&dk->dk_sums.dss_nwritten, nwritten);230}231232void233dataset_kstats_update_read_kstats(dataset_kstats_t *dk, int64_t nread)234{235ASSERT3S(nread, >=, 0);236237if (dk->dk_kstats == NULL)238return;239240wmsum_add(&dk->dk_sums.dss_reads, 1);241wmsum_add(&dk->dk_sums.dss_nread, nread);242}243244void245dataset_kstats_update_nunlinks_kstat(dataset_kstats_t *dk, int64_t delta)246{247if (dk->dk_kstats == NULL)248return;249250wmsum_add(&dk->dk_sums.dss_nunlinks, delta);251}252253void254dataset_kstats_update_nunlinked_kstat(dataset_kstats_t *dk, int64_t delta)255{256if (dk->dk_kstats == NULL)257return;258259wmsum_add(&dk->dk_sums.dss_nunlinked, delta);260}261262263