diff --git a/cmd/ztest.c b/cmd/ztest.c index 0e468e7467..31b9990a1f 100644 --- a/cmd/ztest.c +++ b/cmd/ztest.c @@ -2908,7 +2908,7 @@ ztest_zil_remount(ztest_ds_t *zd, uint64_t id) zil_close(zd->zd_zilog); /* zfsvfs_setup() */ - VERIFY3P(zil_open(os, ztest_get_data), ==, zd->zd_zilog); + VERIFY3P(zil_open(os, ztest_get_data, NULL), ==, zd->zd_zilog); zil_replay(os, zd, ztest_replay_vector); (void) pthread_rwlock_unlock(&zd->zd_zilog_lock); @@ -4378,7 +4378,7 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id) /* * Open the intent log for it. */ - zilog = zil_open(os, ztest_get_data); + zilog = zil_open(os, ztest_get_data, NULL); /* * Put some objects in there, do a little I/O to them, @@ -7304,7 +7304,7 @@ ztest_dataset_open(int d) zilog->zl_parse_lr_count, zilog->zl_replaying_seq); - zilog = zil_open(os, ztest_get_data); + zilog = zil_open(os, ztest_get_data, NULL); if (zilog->zl_replaying_seq != 0 && zilog->zl_replaying_seq < committed_seq) diff --git a/include/sys/dataset_kstats.h b/include/sys/dataset_kstats.h index d6e14572f7..40cf5258a2 100644 --- a/include/sys/dataset_kstats.h +++ b/include/sys/dataset_kstats.h @@ -30,6 +30,7 @@ #include #include #include +#include typedef struct dataset_sum_stats_t { wmsum_t dss_writes; @@ -56,14 +57,19 @@ typedef struct dataset_kstat_values { * entry is removed from the unlinked set */ kstat_named_t dkv_nunlinked; + /* + * Per dataset zil kstats + */ + zil_kstat_values_t dkv_zil_stats; } dataset_kstat_values_t; typedef struct dataset_kstats { dataset_sum_stats_t dk_sums; + zil_sums_t dk_zil_sums; kstat_t *dk_kstats; } dataset_kstats_t; -void dataset_kstats_create(dataset_kstats_t *, objset_t *); +int dataset_kstats_create(dataset_kstats_t *, objset_t *); void dataset_kstats_destroy(dataset_kstats_t *); void dataset_kstats_update_write_kstats(dataset_kstats_t *, int64_t); diff --git a/include/sys/zil.h b/include/sys/zil.h index 3f1c382202..cec04f120c 100644 --- a/include/sys/zil.h +++ b/include/sys/zil.h @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -472,12 +473,34 @@ typedef struct zil_stats { */ kstat_named_t zil_itx_metaslab_slog_count; kstat_named_t zil_itx_metaslab_slog_bytes; -} zil_stats_t; +} zil_kstat_values_t; -#define ZIL_STAT_INCR(stat, val) \ - atomic_add_64(&zil_stats.stat.value.ui64, (val)); -#define ZIL_STAT_BUMP(stat) \ - ZIL_STAT_INCR(stat, 1); +typedef struct zil_sums { + wmsum_t zil_commit_count; + wmsum_t zil_commit_writer_count; + wmsum_t zil_itx_count; + wmsum_t zil_itx_indirect_count; + wmsum_t zil_itx_indirect_bytes; + wmsum_t zil_itx_copied_count; + wmsum_t zil_itx_copied_bytes; + wmsum_t zil_itx_needcopy_count; + wmsum_t zil_itx_needcopy_bytes; + wmsum_t zil_itx_metaslab_normal_count; + wmsum_t zil_itx_metaslab_normal_bytes; + wmsum_t zil_itx_metaslab_slog_count; + wmsum_t zil_itx_metaslab_slog_bytes; +} zil_sums_t; + +#define ZIL_STAT_INCR(zil, stat, val) \ + do { \ + int64_t tmpval = (val); \ + wmsum_add(&(zil_sums_global.stat), tmpval); \ + if ((zil)->zl_sums) \ + wmsum_add(&((zil)->zl_sums->stat), tmpval); \ + } while (0) + +#define ZIL_STAT_BUMP(zil, stat) \ + ZIL_STAT_INCR(zil, stat, 1); typedef int zil_parse_blk_func_t(zilog_t *zilog, const blkptr_t *bp, void *arg, uint64_t txg); @@ -497,7 +520,8 @@ extern void zil_fini(void); extern zilog_t *zil_alloc(objset_t *os, zil_header_t *zh_phys); extern void zil_free(zilog_t *zilog); -extern zilog_t *zil_open(objset_t *os, zil_get_data_t *get_data); +extern zilog_t *zil_open(objset_t *os, zil_get_data_t *get_data, + zil_sums_t *zil_sums); extern void zil_close(zilog_t *zilog); extern void zil_replay(objset_t *os, void *arg, @@ -537,6 +561,11 @@ extern void zil_set_logbias(zilog_t *zilog, uint64_t slogval); extern uint64_t zil_max_copied_data(zilog_t *zilog); extern uint64_t zil_max_log_data(zilog_t *zilog); +extern void zil_sums_init(zil_sums_t *zs); +extern void zil_sums_fini(zil_sums_t *zs); +extern void zil_kstat_values_update(zil_kstat_values_t *zs, + zil_sums_t *zil_sums); + extern int zil_replay_disable; #ifdef __cplusplus diff --git a/include/sys/zil_impl.h b/include/sys/zil_impl.h index f670c3671b..bb85bf6d1e 100644 --- a/include/sys/zil_impl.h +++ b/include/sys/zil_impl.h @@ -222,6 +222,9 @@ struct zilog { * (see zil_max_copied_data()). */ uint64_t zl_max_block_size; + + /* Pointer for per dataset zil sums */ + zil_sums_t *zl_sums; }; typedef struct zil_bp_node { diff --git a/module/os/freebsd/zfs/zfs_vfsops.c b/module/os/freebsd/zfs/zfs_vfsops.c index 0a9461e232..24e06b1a88 100644 --- a/module/os/freebsd/zfs/zfs_vfsops.c +++ b/module/os/freebsd/zfs/zfs_vfsops.c @@ -1027,8 +1027,6 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting) if (error) return (error); - zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data); - /* * If we are not mounting (ie: online recv), then we don't * have to worry about replaying the log as we blocked all @@ -1038,7 +1036,11 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting) boolean_t readonly; ASSERT3P(zfsvfs->z_kstat.dk_kstats, ==, NULL); - dataset_kstats_create(&zfsvfs->z_kstat, zfsvfs->z_os); + error = dataset_kstats_create(&zfsvfs->z_kstat, zfsvfs->z_os); + if (error) + return (error); + zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data, + &zfsvfs->z_kstat.dk_zil_sums); /* * During replay we remove the read only flag to @@ -1109,6 +1111,10 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting) /* restore readonly bit */ if (readonly != 0) zfsvfs->z_vfs->vfs_flag |= VFS_RDONLY; + } else { + ASSERT3P(zfsvfs->z_kstat.dk_kstats, !=, NULL); + zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data, + &zfsvfs->z_kstat.dk_zil_sums); } /* diff --git a/module/os/freebsd/zfs/zvol_os.c b/module/os/freebsd/zfs/zvol_os.c index f6f26157f8..ac030f7532 100644 --- a/module/os/freebsd/zfs/zvol_os.c +++ b/module/os/freebsd/zfs/zvol_os.c @@ -1189,7 +1189,7 @@ zvol_ensure_zilog(zvol_state_t *zv) } if (zv->zv_zilog == NULL) { zv->zv_zilog = zil_open(zv->zv_objset, - zvol_get_data); + zvol_get_data, &zv->zv_kstat.dk_zil_sums); zv->zv_flags |= ZVOL_WRITTEN_TO; /* replay / destroy done in zvol_os_create_minor() */ VERIFY0(zv->zv_zilog->zl_header->zh_flags & @@ -1422,8 +1422,12 @@ zvol_os_create_minor(const char *name) zv->zv_volsize = volsize; zv->zv_objset = os; + ASSERT3P(zv->zv_kstat.dk_kstats, ==, NULL); + error = dataset_kstats_create(&zv->zv_kstat, zv->zv_objset); + if (error) + goto out_dmu_objset_disown; ASSERT3P(zv->zv_zilog, ==, NULL); - zv->zv_zilog = zil_open(os, zvol_get_data); + zv->zv_zilog = zil_open(os, zvol_get_data, &zv->zv_kstat.dk_zil_sums); if (spa_writeable(dmu_objset_spa(os))) { if (zil_replay_disable) zil_destroy(zv->zv_zilog, B_FALSE); @@ -1432,8 +1436,6 @@ zvol_os_create_minor(const char *name) } zil_close(zv->zv_zilog); zv->zv_zilog = NULL; - ASSERT3P(zv->zv_kstat.dk_kstats, ==, NULL); - dataset_kstats_create(&zv->zv_kstat, zv->zv_objset); /* TODO: prefetch for geom tasting */ diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c index 4fcda78818..eac3dcb6a5 100644 --- a/module/os/linux/zfs/zfs_vfsops.c +++ b/module/os/linux/zfs/zfs_vfsops.c @@ -848,8 +848,6 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting) if (error) return (error); - zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data); - /* * If we are not mounting (ie: online recv), then we don't * have to worry about replaying the log as we blocked all @@ -857,7 +855,11 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting) */ if (mounting) { ASSERT3P(zfsvfs->z_kstat.dk_kstats, ==, NULL); - dataset_kstats_create(&zfsvfs->z_kstat, zfsvfs->z_os); + error = dataset_kstats_create(&zfsvfs->z_kstat, zfsvfs->z_os); + if (error) + return (error); + zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data, + &zfsvfs->z_kstat.dk_zil_sums); /* * During replay we remove the read only flag to @@ -921,6 +923,10 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting) /* restore readonly bit */ if (readonly != 0) readonly_changed_cb(zfsvfs, B_TRUE); + } else { + ASSERT3P(zfsvfs->z_kstat.dk_kstats, !=, NULL); + zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data, + &zfsvfs->z_kstat.dk_zil_sums); } /* diff --git a/module/os/linux/zfs/zvol_os.c b/module/os/linux/zfs/zvol_os.c index 68aeb14580..18b9fbd0ea 100644 --- a/module/os/linux/zfs/zvol_os.c +++ b/module/os/linux/zfs/zvol_os.c @@ -558,7 +558,7 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq, rw_enter(&zv->zv_suspend_lock, RW_WRITER); if (zv->zv_zilog == NULL) { zv->zv_zilog = zil_open(zv->zv_objset, - zvol_get_data); + zvol_get_data, &zv->zv_kstat.dk_zil_sums); zv->zv_flags |= ZVOL_WRITTEN_TO; /* replay / destroy done in zvol_create_minor */ VERIFY0((zv->zv_zilog->zl_header->zh_flags & @@ -1408,8 +1408,12 @@ zvol_os_create_minor(const char *name) blk_queue_flag_set(QUEUE_FLAG_SCSI_PASSTHROUGH, zv->zv_zso->zvo_queue); #endif + ASSERT3P(zv->zv_kstat.dk_kstats, ==, NULL); + error = dataset_kstats_create(&zv->zv_kstat, zv->zv_objset); + if (error) + goto out_dmu_objset_disown; ASSERT3P(zv->zv_zilog, ==, NULL); - zv->zv_zilog = zil_open(os, zvol_get_data); + zv->zv_zilog = zil_open(os, zvol_get_data, &zv->zv_kstat.dk_zil_sums); if (spa_writeable(dmu_objset_spa(os))) { if (zil_replay_disable) zil_destroy(zv->zv_zilog, B_FALSE); @@ -1418,8 +1422,6 @@ zvol_os_create_minor(const char *name) } zil_close(zv->zv_zilog); zv->zv_zilog = NULL; - ASSERT3P(zv->zv_kstat.dk_kstats, ==, NULL); - dataset_kstats_create(&zv->zv_kstat, zv->zv_objset); /* * When udev detects the addition of the device it will immediately diff --git a/module/zfs/dataset_kstats.c b/module/zfs/dataset_kstats.c index 9130574c57..b63f42a21e 100644 --- a/module/zfs/dataset_kstats.c +++ b/module/zfs/dataset_kstats.c @@ -37,18 +37,33 @@ static dataset_kstat_values_t empty_dataset_kstats = { { "nread", KSTAT_DATA_UINT64 }, { "nunlinks", KSTAT_DATA_UINT64 }, { "nunlinked", KSTAT_DATA_UINT64 }, + { + { "zil_commit_count", KSTAT_DATA_UINT64 }, + { "zil_commit_writer_count", KSTAT_DATA_UINT64 }, + { "zil_itx_count", KSTAT_DATA_UINT64 }, + { "zil_itx_indirect_count", KSTAT_DATA_UINT64 }, + { "zil_itx_indirect_bytes", KSTAT_DATA_UINT64 }, + { "zil_itx_copied_count", KSTAT_DATA_UINT64 }, + { "zil_itx_copied_bytes", KSTAT_DATA_UINT64 }, + { "zil_itx_needcopy_count", KSTAT_DATA_UINT64 }, + { "zil_itx_needcopy_bytes", KSTAT_DATA_UINT64 }, + { "zil_itx_metaslab_normal_count", KSTAT_DATA_UINT64 }, + { "zil_itx_metaslab_normal_bytes", KSTAT_DATA_UINT64 }, + { "zil_itx_metaslab_slog_count", KSTAT_DATA_UINT64 }, + { "zil_itx_metaslab_slog_bytes", KSTAT_DATA_UINT64 } + } }; static int dataset_kstats_update(kstat_t *ksp, int rw) { dataset_kstats_t *dk = ksp->ks_private; - ASSERT3P(dk->dk_kstats->ks_data, ==, ksp->ks_data); + dataset_kstat_values_t *dkv = ksp->ks_data; + ASSERT3P(dk->dk_kstats->ks_data, ==, dkv); if (rw == KSTAT_WRITE) return (EACCES); - dataset_kstat_values_t *dkv = dk->dk_kstats->ks_data; dkv->dkv_writes.value.ui64 = wmsum_value(&dk->dk_sums.dss_writes); dkv->dkv_nwritten.value.ui64 = @@ -62,10 +77,12 @@ dataset_kstats_update(kstat_t *ksp, int rw) dkv->dkv_nunlinked.value.ui64 = wmsum_value(&dk->dk_sums.dss_nunlinked); + zil_kstat_values_update(&dkv->dkv_zil_stats, &dk->dk_zil_sums); + return (0); } -void +int dataset_kstats_create(dataset_kstats_t *dk, objset_t *objset) { /* @@ -75,7 +92,7 @@ dataset_kstats_create(dataset_kstats_t *dk, objset_t *objset) * a filesystem with many snapshots, we skip them for now. */ if (dmu_objset_is_snapshot(objset)) - return; + return (0); /* * At the time of this writing, KSTAT_STRLEN is 255 in Linux, @@ -94,13 +111,13 @@ dataset_kstats_create(dataset_kstats_t *dk, objset_t *objset) zfs_dbgmsg("failed to create dataset kstat for objset %lld: " " snprintf() for kstat module name returned %d", (unsigned long long)dmu_objset_id(objset), n); - return; + return (SET_ERROR(EINVAL)); } else if (n >= KSTAT_STRLEN) { zfs_dbgmsg("failed to create dataset kstat for objset %lld: " "kstat module name length (%d) exceeds limit (%d)", (unsigned long long)dmu_objset_id(objset), n, KSTAT_STRLEN); - return; + return (SET_ERROR(ENAMETOOLONG)); } char kstat_name[KSTAT_STRLEN]; @@ -110,7 +127,7 @@ dataset_kstats_create(dataset_kstats_t *dk, objset_t *objset) zfs_dbgmsg("failed to create dataset kstat for objset %lld: " " snprintf() for kstat name returned %d", (unsigned long long)dmu_objset_id(objset), n); - return; + return (SET_ERROR(EINVAL)); } ASSERT3U(n, <, KSTAT_STRLEN); @@ -119,7 +136,7 @@ dataset_kstats_create(dataset_kstats_t *dk, objset_t *objset) sizeof (empty_dataset_kstats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL); if (kstat == NULL) - return; + return (SET_ERROR(ENOMEM)); dataset_kstat_values_t *dk_kstats = kmem_alloc(sizeof (empty_dataset_kstats), KM_SLEEP); @@ -137,15 +154,17 @@ dataset_kstats_create(dataset_kstats_t *dk, objset_t *objset) kstat->ks_private = dk; kstat->ks_data_size += ZFS_MAX_DATASET_NAME_LEN; - kstat_install(kstat); - dk->dk_kstats = kstat; - wmsum_init(&dk->dk_sums.dss_writes, 0); wmsum_init(&dk->dk_sums.dss_nwritten, 0); wmsum_init(&dk->dk_sums.dss_reads, 0); wmsum_init(&dk->dk_sums.dss_nread, 0); wmsum_init(&dk->dk_sums.dss_nunlinks, 0); wmsum_init(&dk->dk_sums.dss_nunlinked, 0); + zil_sums_init(&dk->dk_zil_sums); + + dk->dk_kstats = kstat; + kstat_install(kstat); + return (0); } void @@ -155,19 +174,19 @@ dataset_kstats_destroy(dataset_kstats_t *dk) return; dataset_kstat_values_t *dkv = dk->dk_kstats->ks_data; + kstat_delete(dk->dk_kstats); + dk->dk_kstats = NULL; kmem_free(KSTAT_NAMED_STR_PTR(&dkv->dkv_ds_name), KSTAT_NAMED_STR_BUFLEN(&dkv->dkv_ds_name)); kmem_free(dkv, sizeof (empty_dataset_kstats)); - kstat_delete(dk->dk_kstats); - dk->dk_kstats = NULL; - wmsum_fini(&dk->dk_sums.dss_writes); wmsum_fini(&dk->dk_sums.dss_nwritten); wmsum_fini(&dk->dk_sums.dss_reads); wmsum_fini(&dk->dk_sums.dss_nread); wmsum_fini(&dk->dk_sums.dss_nunlinks); wmsum_fini(&dk->dk_sums.dss_nunlinked); + zil_sums_fini(&dk->dk_zil_sums); } void diff --git a/module/zfs/zil.c b/module/zfs/zil.c index bffae6dfd7..4864e0ccad 100644 --- a/module/zfs/zil.c +++ b/module/zfs/zil.c @@ -43,6 +43,7 @@ #include #include #include +#include /* * The ZFS Intent Log (ZIL) saves "transaction records" (itxs) of system @@ -94,7 +95,7 @@ static int zfs_commit_timeout_pct = 5; /* * See zil.h for more information about these fields. */ -static zil_stats_t zil_stats = { +static zil_kstat_values_t zil_stats = { { "zil_commit_count", KSTAT_DATA_UINT64 }, { "zil_commit_writer_count", KSTAT_DATA_UINT64 }, { "zil_itx_count", KSTAT_DATA_UINT64 }, @@ -110,7 +111,8 @@ static zil_stats_t zil_stats = { { "zil_itx_metaslab_slog_bytes", KSTAT_DATA_UINT64 }, }; -static kstat_t *zil_ksp; +static zil_sums_t zil_sums_global; +static kstat_t *zil_kstats_global; /* * Disable intent logging replay. This global ZIL switch affects all pools. @@ -213,6 +215,21 @@ zil_init_log_chain(zilog_t *zilog, blkptr_t *bp) zc->zc_word[ZIL_ZC_SEQ] = 1ULL; } +static int +zil_kstats_global_update(kstat_t *ksp, int rw) +{ + zil_kstat_values_t *zs = ksp->ks_data; + ASSERT3P(&zil_stats, ==, zs); + + if (rw == KSTAT_WRITE) { + return (SET_ERROR(EACCES)); + } + + zil_kstat_values_update(zs, &zil_sums_global); + + return (0); +} + /* * Read a log block and make sure it's valid. */ @@ -337,6 +354,73 @@ zil_read_log_data(zilog_t *zilog, const lr_write_t *lr, void *wbuf) return (error); } +void +zil_sums_init(zil_sums_t *zs) +{ + wmsum_init(&zs->zil_commit_count, 0); + wmsum_init(&zs->zil_commit_writer_count, 0); + wmsum_init(&zs->zil_itx_count, 0); + wmsum_init(&zs->zil_itx_indirect_count, 0); + wmsum_init(&zs->zil_itx_indirect_bytes, 0); + wmsum_init(&zs->zil_itx_copied_count, 0); + wmsum_init(&zs->zil_itx_copied_bytes, 0); + wmsum_init(&zs->zil_itx_needcopy_count, 0); + wmsum_init(&zs->zil_itx_needcopy_bytes, 0); + wmsum_init(&zs->zil_itx_metaslab_normal_count, 0); + wmsum_init(&zs->zil_itx_metaslab_normal_bytes, 0); + wmsum_init(&zs->zil_itx_metaslab_slog_count, 0); + wmsum_init(&zs->zil_itx_metaslab_slog_bytes, 0); +} + +void +zil_sums_fini(zil_sums_t *zs) +{ + wmsum_fini(&zs->zil_commit_count); + wmsum_fini(&zs->zil_commit_writer_count); + wmsum_fini(&zs->zil_itx_count); + wmsum_fini(&zs->zil_itx_indirect_count); + wmsum_fini(&zs->zil_itx_indirect_bytes); + wmsum_fini(&zs->zil_itx_copied_count); + wmsum_fini(&zs->zil_itx_copied_bytes); + wmsum_fini(&zs->zil_itx_needcopy_count); + wmsum_fini(&zs->zil_itx_needcopy_bytes); + wmsum_fini(&zs->zil_itx_metaslab_normal_count); + wmsum_fini(&zs->zil_itx_metaslab_normal_bytes); + wmsum_fini(&zs->zil_itx_metaslab_slog_count); + wmsum_fini(&zs->zil_itx_metaslab_slog_bytes); +} + +void +zil_kstat_values_update(zil_kstat_values_t *zs, zil_sums_t *zil_sums) +{ + zs->zil_commit_count.value.ui64 = + wmsum_value(&zil_sums->zil_commit_count); + zs->zil_commit_writer_count.value.ui64 = + wmsum_value(&zil_sums->zil_commit_writer_count); + zs->zil_itx_count.value.ui64 = + wmsum_value(&zil_sums->zil_itx_count); + zs->zil_itx_indirect_count.value.ui64 = + wmsum_value(&zil_sums->zil_itx_indirect_count); + zs->zil_itx_indirect_bytes.value.ui64 = + wmsum_value(&zil_sums->zil_itx_indirect_bytes); + zs->zil_itx_copied_count.value.ui64 = + wmsum_value(&zil_sums->zil_itx_copied_count); + zs->zil_itx_copied_bytes.value.ui64 = + wmsum_value(&zil_sums->zil_itx_copied_bytes); + zs->zil_itx_needcopy_count.value.ui64 = + wmsum_value(&zil_sums->zil_itx_needcopy_count); + zs->zil_itx_needcopy_bytes.value.ui64 = + wmsum_value(&zil_sums->zil_itx_needcopy_bytes); + zs->zil_itx_metaslab_normal_count.value.ui64 = + wmsum_value(&zil_sums->zil_itx_metaslab_normal_count); + zs->zil_itx_metaslab_normal_bytes.value.ui64 = + wmsum_value(&zil_sums->zil_itx_metaslab_normal_bytes); + zs->zil_itx_metaslab_slog_count.value.ui64 = + wmsum_value(&zil_sums->zil_itx_metaslab_slog_count); + zs->zil_itx_metaslab_slog_bytes.value.ui64 = + wmsum_value(&zil_sums->zil_itx_metaslab_slog_bytes); +} + /* * Parse the intent log, and call parse_func for each valid record within. */ @@ -1644,11 +1728,13 @@ zil_lwb_write_issue(zilog_t *zilog, lwb_t *lwb) BP_ZERO(bp); error = zio_alloc_zil(spa, zilog->zl_os, txg, bp, zil_blksz, &slog); if (slog) { - ZIL_STAT_BUMP(zil_itx_metaslab_slog_count); - ZIL_STAT_INCR(zil_itx_metaslab_slog_bytes, lwb->lwb_nused); + ZIL_STAT_BUMP(zilog, zil_itx_metaslab_slog_count); + ZIL_STAT_INCR(zilog, zil_itx_metaslab_slog_bytes, + lwb->lwb_nused); } else { - ZIL_STAT_BUMP(zil_itx_metaslab_normal_count); - ZIL_STAT_INCR(zil_itx_metaslab_normal_bytes, lwb->lwb_nused); + ZIL_STAT_BUMP(zilog, zil_itx_metaslab_normal_count); + ZIL_STAT_INCR(zilog, zil_itx_metaslab_normal_bytes, + lwb->lwb_nused); } if (error == 0) { ASSERT3U(bp->blk_birth, ==, txg); @@ -1818,7 +1904,7 @@ cont: lrcb = (lr_t *)lr_buf; /* Like lrc, but inside lwb. */ lrwb = (lr_write_t *)lrcb; /* Like lrw, but inside lwb. */ - ZIL_STAT_BUMP(zil_itx_count); + ZIL_STAT_BUMP(zilog, zil_itx_count); /* * If it's a write, fetch the data or get its blkptr as appropriate. @@ -1827,8 +1913,9 @@ cont: if (txg > spa_freeze_txg(zilog->zl_spa)) txg_wait_synced(zilog->zl_dmu_pool, txg); if (itx->itx_wr_state == WR_COPIED) { - ZIL_STAT_BUMP(zil_itx_copied_count); - ZIL_STAT_INCR(zil_itx_copied_bytes, lrw->lr_length); + ZIL_STAT_BUMP(zilog, zil_itx_copied_count); + ZIL_STAT_INCR(zilog, zil_itx_copied_bytes, + lrw->lr_length); } else { char *dbuf; int error; @@ -1840,13 +1927,14 @@ cont: lrwb->lr_length = dnow; lrw->lr_offset += dnow; lrw->lr_length -= dnow; - ZIL_STAT_BUMP(zil_itx_needcopy_count); - ZIL_STAT_INCR(zil_itx_needcopy_bytes, dnow); + ZIL_STAT_BUMP(zilog, zil_itx_needcopy_count); + ZIL_STAT_INCR(zilog, zil_itx_needcopy_bytes, + dnow); } else { ASSERT3S(itx->itx_wr_state, ==, WR_INDIRECT); dbuf = NULL; - ZIL_STAT_BUMP(zil_itx_indirect_count); - ZIL_STAT_INCR(zil_itx_indirect_bytes, + ZIL_STAT_BUMP(zilog, zil_itx_indirect_count); + ZIL_STAT_INCR(zilog, zil_itx_indirect_bytes, lrw->lr_length); } @@ -2611,7 +2699,7 @@ zil_commit_writer(zilog_t *zilog, zil_commit_waiter_t *zcw) goto out; } - ZIL_STAT_BUMP(zil_commit_writer_count); + ZIL_STAT_BUMP(zilog, zil_commit_writer_count); zil_get_commit_list(zilog); zil_prune_commit_list(zilog); @@ -3088,7 +3176,7 @@ zil_commit(zilog_t *zilog, uint64_t foid) void zil_commit_impl(zilog_t *zilog, uint64_t foid) { - ZIL_STAT_BUMP(zil_commit_count); + ZIL_STAT_BUMP(zilog, zil_commit_count); /* * Move the "async" itxs for the specified foid to the "sync" @@ -3271,13 +3359,16 @@ zil_init(void) zil_zcw_cache = kmem_cache_create("zil_zcw_cache", sizeof (zil_commit_waiter_t), 0, NULL, NULL, NULL, NULL, NULL, 0); - zil_ksp = kstat_create("zfs", 0, "zil", "misc", + zil_sums_init(&zil_sums_global); + zil_kstats_global = kstat_create("zfs", 0, "zil", "misc", KSTAT_TYPE_NAMED, sizeof (zil_stats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL); - if (zil_ksp != NULL) { - zil_ksp->ks_data = &zil_stats; - kstat_install(zil_ksp); + if (zil_kstats_global != NULL) { + zil_kstats_global->ks_data = &zil_stats; + zil_kstats_global->ks_update = zil_kstats_global_update; + zil_kstats_global->ks_private = NULL; + kstat_install(zil_kstats_global); } } @@ -3287,10 +3378,12 @@ zil_fini(void) kmem_cache_destroy(zil_zcw_cache); kmem_cache_destroy(zil_lwb_cache); - if (zil_ksp != NULL) { - kstat_delete(zil_ksp); - zil_ksp = NULL; + if (zil_kstats_global != NULL) { + kstat_delete(zil_kstats_global); + zil_kstats_global = NULL; } + + zil_sums_fini(&zil_sums_global); } void @@ -3388,7 +3481,7 @@ zil_free(zilog_t *zilog) * Open an intent log. */ zilog_t * -zil_open(objset_t *os, zil_get_data_t *get_data) +zil_open(objset_t *os, zil_get_data_t *get_data, zil_sums_t *zil_sums) { zilog_t *zilog = dmu_objset_zil(os); @@ -3397,6 +3490,7 @@ zil_open(objset_t *os, zil_get_data_t *get_data) ASSERT(list_is_empty(&zilog->zl_lwb_list)); zilog->zl_get_data = get_data; + zilog->zl_sums = zil_sums; return (zilog); } @@ -3838,6 +3932,9 @@ EXPORT_SYMBOL(zil_lwb_add_block); EXPORT_SYMBOL(zil_bp_tree_add); EXPORT_SYMBOL(zil_set_sync); EXPORT_SYMBOL(zil_set_logbias); +EXPORT_SYMBOL(zil_sums_init); +EXPORT_SYMBOL(zil_sums_fini); +EXPORT_SYMBOL(zil_kstat_values_update); ZFS_MODULE_PARAM(zfs, zfs_, commit_timeout_pct, INT, ZMOD_RW, "ZIL block open timeout percentage");