]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/openzfs/module/zfs/dataset_kstats.c
contrib/bsddialog: Import version 0.3
[FreeBSD/FreeBSD.git] / sys / contrib / openzfs / module / zfs / dataset_kstats.c
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * 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.LICENSE
9  * or https://opensource.org/licenses/CDDL-1.0.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21
22 /*
23  * Copyright (c) 2018 by Delphix. All rights reserved.
24  * Copyright (c) 2018 Datto Inc.
25  */
26
27 #include <sys/dataset_kstats.h>
28 #include <sys/dmu_objset.h>
29 #include <sys/dsl_dataset.h>
30 #include <sys/spa.h>
31
32 static 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_itx_count",                      KSTAT_DATA_UINT64 },
44         { "zil_itx_indirect_count",             KSTAT_DATA_UINT64 },
45         { "zil_itx_indirect_bytes",             KSTAT_DATA_UINT64 },
46         { "zil_itx_copied_count",               KSTAT_DATA_UINT64 },
47         { "zil_itx_copied_bytes",               KSTAT_DATA_UINT64 },
48         { "zil_itx_needcopy_count",             KSTAT_DATA_UINT64 },
49         { "zil_itx_needcopy_bytes",             KSTAT_DATA_UINT64 },
50         { "zil_itx_metaslab_normal_count",      KSTAT_DATA_UINT64 },
51         { "zil_itx_metaslab_normal_bytes",      KSTAT_DATA_UINT64 },
52         { "zil_itx_metaslab_slog_count",        KSTAT_DATA_UINT64 },
53         { "zil_itx_metaslab_slog_bytes",        KSTAT_DATA_UINT64 }
54         }
55 };
56
57 static int
58 dataset_kstats_update(kstat_t *ksp, int rw)
59 {
60         dataset_kstats_t *dk = ksp->ks_private;
61         dataset_kstat_values_t *dkv = ksp->ks_data;
62         ASSERT3P(dk->dk_kstats->ks_data, ==, dkv);
63
64         if (rw == KSTAT_WRITE)
65                 return (EACCES);
66
67         dkv->dkv_writes.value.ui64 =
68             wmsum_value(&dk->dk_sums.dss_writes);
69         dkv->dkv_nwritten.value.ui64 =
70             wmsum_value(&dk->dk_sums.dss_nwritten);
71         dkv->dkv_reads.value.ui64 =
72             wmsum_value(&dk->dk_sums.dss_reads);
73         dkv->dkv_nread.value.ui64 =
74             wmsum_value(&dk->dk_sums.dss_nread);
75         dkv->dkv_nunlinks.value.ui64 =
76             wmsum_value(&dk->dk_sums.dss_nunlinks);
77         dkv->dkv_nunlinked.value.ui64 =
78             wmsum_value(&dk->dk_sums.dss_nunlinked);
79
80         zil_kstat_values_update(&dkv->dkv_zil_stats, &dk->dk_zil_sums);
81
82         return (0);
83 }
84
85 int
86 dataset_kstats_create(dataset_kstats_t *dk, objset_t *objset)
87 {
88         /*
89          * There should not be anything wrong with having kstats for
90          * snapshots. Since we are not sure how useful they would be
91          * though nor how much their memory overhead would matter in
92          * a filesystem with many snapshots, we skip them for now.
93          */
94         if (dmu_objset_is_snapshot(objset))
95                 return (0);
96
97         /*
98          * At the time of this writing, KSTAT_STRLEN is 255 in Linux,
99          * and the spa_name can theoretically be up to 256 characters.
100          * In reality though the spa_name can be 240 characters max
101          * [see origin directory name check in pool_namecheck()]. Thus,
102          * the naming scheme for the module name below should not cause
103          * any truncations. In the event that a truncation does happen
104          * though, due to some future change, we silently skip creating
105          * the kstat and log the event.
106          */
107         char kstat_module_name[KSTAT_STRLEN];
108         int n = snprintf(kstat_module_name, sizeof (kstat_module_name),
109             "zfs/%s", spa_name(dmu_objset_spa(objset)));
110         if (n < 0) {
111                 zfs_dbgmsg("failed to create dataset kstat for objset %lld: "
112                     " snprintf() for kstat module name returned %d",
113                     (unsigned long long)dmu_objset_id(objset), n);
114                 return (SET_ERROR(EINVAL));
115         } else if (n >= KSTAT_STRLEN) {
116                 zfs_dbgmsg("failed to create dataset kstat for objset %lld: "
117                     "kstat module name length (%d) exceeds limit (%d)",
118                     (unsigned long long)dmu_objset_id(objset),
119                     n, KSTAT_STRLEN);
120                 return (SET_ERROR(ENAMETOOLONG));
121         }
122
123         char kstat_name[KSTAT_STRLEN];
124         n = snprintf(kstat_name, sizeof (kstat_name), "objset-0x%llx",
125             (unsigned long long)dmu_objset_id(objset));
126         if (n < 0) {
127                 zfs_dbgmsg("failed to create dataset kstat for objset %lld: "
128                     " snprintf() for kstat name returned %d",
129                     (unsigned long long)dmu_objset_id(objset), n);
130                 return (SET_ERROR(EINVAL));
131         }
132         ASSERT3U(n, <, KSTAT_STRLEN);
133
134         kstat_t *kstat = kstat_create(kstat_module_name, 0, kstat_name,
135             "dataset", KSTAT_TYPE_NAMED,
136             sizeof (empty_dataset_kstats) / sizeof (kstat_named_t),
137             KSTAT_FLAG_VIRTUAL);
138         if (kstat == NULL)
139                 return (SET_ERROR(ENOMEM));
140
141         dataset_kstat_values_t *dk_kstats =
142             kmem_alloc(sizeof (empty_dataset_kstats), KM_SLEEP);
143         memcpy(dk_kstats, &empty_dataset_kstats,
144             sizeof (empty_dataset_kstats));
145
146         char *ds_name = kmem_zalloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);
147         dsl_dataset_name(objset->os_dsl_dataset, ds_name);
148         KSTAT_NAMED_STR_PTR(&dk_kstats->dkv_ds_name) = ds_name;
149         KSTAT_NAMED_STR_BUFLEN(&dk_kstats->dkv_ds_name) =
150             ZFS_MAX_DATASET_NAME_LEN;
151
152         kstat->ks_data = dk_kstats;
153         kstat->ks_update = dataset_kstats_update;
154         kstat->ks_private = dk;
155         kstat->ks_data_size += ZFS_MAX_DATASET_NAME_LEN;
156
157         wmsum_init(&dk->dk_sums.dss_writes, 0);
158         wmsum_init(&dk->dk_sums.dss_nwritten, 0);
159         wmsum_init(&dk->dk_sums.dss_reads, 0);
160         wmsum_init(&dk->dk_sums.dss_nread, 0);
161         wmsum_init(&dk->dk_sums.dss_nunlinks, 0);
162         wmsum_init(&dk->dk_sums.dss_nunlinked, 0);
163         zil_sums_init(&dk->dk_zil_sums);
164
165         dk->dk_kstats = kstat;
166         kstat_install(kstat);
167         return (0);
168 }
169
170 void
171 dataset_kstats_destroy(dataset_kstats_t *dk)
172 {
173         if (dk->dk_kstats == NULL)
174                 return;
175
176         dataset_kstat_values_t *dkv = dk->dk_kstats->ks_data;
177         kstat_delete(dk->dk_kstats);
178         dk->dk_kstats = NULL;
179         kmem_free(KSTAT_NAMED_STR_PTR(&dkv->dkv_ds_name),
180             KSTAT_NAMED_STR_BUFLEN(&dkv->dkv_ds_name));
181         kmem_free(dkv, sizeof (empty_dataset_kstats));
182
183         wmsum_fini(&dk->dk_sums.dss_writes);
184         wmsum_fini(&dk->dk_sums.dss_nwritten);
185         wmsum_fini(&dk->dk_sums.dss_reads);
186         wmsum_fini(&dk->dk_sums.dss_nread);
187         wmsum_fini(&dk->dk_sums.dss_nunlinks);
188         wmsum_fini(&dk->dk_sums.dss_nunlinked);
189         zil_sums_fini(&dk->dk_zil_sums);
190 }
191
192 void
193 dataset_kstats_update_write_kstats(dataset_kstats_t *dk,
194     int64_t nwritten)
195 {
196         ASSERT3S(nwritten, >=, 0);
197
198         if (dk->dk_kstats == NULL)
199                 return;
200
201         wmsum_add(&dk->dk_sums.dss_writes, 1);
202         wmsum_add(&dk->dk_sums.dss_nwritten, nwritten);
203 }
204
205 void
206 dataset_kstats_update_read_kstats(dataset_kstats_t *dk,
207     int64_t nread)
208 {
209         ASSERT3S(nread, >=, 0);
210
211         if (dk->dk_kstats == NULL)
212                 return;
213
214         wmsum_add(&dk->dk_sums.dss_reads, 1);
215         wmsum_add(&dk->dk_sums.dss_nread, nread);
216 }
217
218 void
219 dataset_kstats_update_nunlinks_kstat(dataset_kstats_t *dk, int64_t delta)
220 {
221         if (dk->dk_kstats == NULL)
222                 return;
223
224         wmsum_add(&dk->dk_sums.dss_nunlinks, delta);
225 }
226
227 void
228 dataset_kstats_update_nunlinked_kstat(dataset_kstats_t *dk, int64_t delta)
229 {
230         if (dk->dk_kstats == NULL)
231                 return;
232
233         wmsum_add(&dk->dk_sums.dss_nunlinked, delta);
234 }