]> git.proxmox.com Git - mirror_zfs.git/blame - module/zfs/spa_stats.c
Remove db_state DB_NOFILL checks from syncing context
[mirror_zfs.git] / module / zfs / spa_stats.c
CommitLineData
1421c891
PS
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
1d3ba0bf 9 * or https://opensource.org/licenses/CDDL-1.0.
1421c891
PS
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#include <sys/zfs_context.h>
23#include <sys/spa_impl.h>
379ca9cf 24#include <sys/vdev_impl.h>
f0ed6c74
TH
25#include <sys/spa.h>
26#include <zfs_comutil.h>
1421c891
PS
27
28/*
29 * Keeps stats on last N reads per spa_t, disabled by default.
30 */
fdc2d303 31static uint_t zfs_read_history = B_FALSE;
1421c891
PS
32
33/*
34 * Include cache hits in history, disabled by default.
35 */
18168da7 36static int zfs_read_history_hits = B_FALSE;
1421c891 37
0b1401ee 38/*
01ff0d75 39 * Keeps stats on the last 100 txgs by default.
0b1401ee 40 */
fdc2d303 41static uint_t zfs_txg_history = 100;
0b1401ee 42
379ca9cf
OF
43/*
44 * Keeps stats on the last N MMP updates, disabled by default.
45 */
fdc2d303 46static uint_t zfs_multihost_history = B_FALSE;
379ca9cf 47
1421c891
PS
48/*
49 * ==========================================================================
50 * SPA Read History Routines
51 * ==========================================================================
52 */
53
54/*
55 * Read statistics - Information exported regarding each arc_read call
56 */
57typedef struct spa_read_history {
1421c891
PS
58 hrtime_t start; /* time read completed */
59 uint64_t objset; /* read from this objset */
60 uint64_t object; /* read of this object number */
61 uint64_t level; /* block's indirection level */
62 uint64_t blkid; /* read of this block id */
63 char origin[24]; /* read originated from here */
64 uint32_t aflags; /* ARC flags (cached, prefetch, etc.) */
65 pid_t pid; /* PID of task doing read */
66 char comm[16]; /* process name of task doing read */
d1261452 67 procfs_list_node_t srh_node;
1421c891
PS
68} spa_read_history_t;
69
70static int
d1261452 71spa_read_history_show_header(struct seq_file *f)
1421c891 72{
d1261452 73 seq_printf(f, "%-8s %-16s %-8s %-8s %-8s %-8s %-8s "
1421c891
PS
74 "%-24s %-8s %-16s\n", "UID", "start", "objset", "object",
75 "level", "blkid", "aflags", "origin", "pid", "process");
1421c891
PS
76
77 return (0);
78}
79
80static int
d1261452 81spa_read_history_show(struct seq_file *f, void *data)
1421c891
PS
82{
83 spa_read_history_t *srh = (spa_read_history_t *)data;
84
d1261452 85 seq_printf(f, "%-8llu %-16llu 0x%-6llx "
1421c891 86 "%-8lli %-8lli %-8lli 0x%-6x %-24s %-8i %-16s\n",
d1261452 87 (u_longlong_t)srh->srh_node.pln_id, srh->start,
1421c891
PS
88 (longlong_t)srh->objset, (longlong_t)srh->object,
89 (longlong_t)srh->level, (longlong_t)srh->blkid,
90 srh->aflags, srh->origin, srh->pid, srh->comm);
1421c891
PS
91
92 return (0);
93}
94
d1261452
JG
95/* Remove oldest elements from list until there are no more than 'size' left */
96static void
97spa_read_history_truncate(spa_history_list_t *shl, unsigned int size)
1421c891 98{
d1261452
JG
99 spa_read_history_t *srh;
100 while (shl->size > size) {
101 srh = list_remove_head(&shl->procfs_list.pl_list);
102 ASSERT3P(srh, !=, NULL);
103 kmem_free(srh, sizeof (spa_read_history_t));
104 shl->size--;
105 }
1421c891 106
d1261452
JG
107 if (size == 0)
108 ASSERT(list_is_empty(&shl->procfs_list.pl_list));
1421c891
PS
109}
110
1421c891 111static int
d1261452 112spa_read_history_clear(procfs_list_t *procfs_list)
1421c891 113{
d1261452
JG
114 spa_history_list_t *shl = procfs_list->pl_private;
115 mutex_enter(&procfs_list->pl_lock);
116 spa_read_history_truncate(shl, 0);
117 mutex_exit(&procfs_list->pl_lock);
1421c891
PS
118 return (0);
119}
120
121static void
122spa_read_history_init(spa_t *spa)
123{
d1261452 124 spa_history_list_t *shl = &spa->spa_stats.read_history;
1421c891 125
d1261452 126 shl->size = 0;
d1261452 127 shl->procfs_list.pl_private = shl;
7b8363d7
MM
128 procfs_list_install("zfs",
129 spa_name(spa),
d1261452 130 "reads",
a887d653 131 0600,
d1261452
JG
132 &shl->procfs_list,
133 spa_read_history_show,
134 spa_read_history_show_header,
135 spa_read_history_clear,
136 offsetof(spa_read_history_t, srh_node));
1421c891
PS
137}
138
139static void
140spa_read_history_destroy(spa_t *spa)
141{
d1261452
JG
142 spa_history_list_t *shl = &spa->spa_stats.read_history;
143 procfs_list_uninstall(&shl->procfs_list);
144 spa_read_history_truncate(shl, 0);
145 procfs_list_destroy(&shl->procfs_list);
1421c891
PS
146}
147
148void
5dbd68a3 149spa_read_history_add(spa_t *spa, const zbookmark_phys_t *zb, uint32_t aflags)
1421c891 150{
d1261452
JG
151 spa_history_list_t *shl = &spa->spa_stats.read_history;
152 spa_read_history_t *srh;
1421c891
PS
153
154 ASSERT3P(spa, !=, NULL);
155 ASSERT3P(zb, !=, NULL);
156
d1261452 157 if (zfs_read_history == 0 && shl->size == 0)
1421c891
PS
158 return;
159
2a432414 160 if (zfs_read_history_hits == 0 && (aflags & ARC_FLAG_CACHED))
1421c891
PS
161 return;
162
79c76d5b 163 srh = kmem_zalloc(sizeof (spa_read_history_t), KM_SLEEP);
d1d7e268 164 strlcpy(srh->comm, getcomm(), sizeof (srh->comm));
1421c891
PS
165 srh->start = gethrtime();
166 srh->objset = zb->zb_objset;
167 srh->object = zb->zb_object;
168 srh->level = zb->zb_level;
169 srh->blkid = zb->zb_blkid;
170 srh->aflags = aflags;
171 srh->pid = getpid();
172
d1261452 173 mutex_enter(&shl->procfs_list.pl_lock);
1421c891 174
d1261452
JG
175 procfs_list_add(&shl->procfs_list, srh);
176 shl->size++;
1421c891 177
d1261452 178 spa_read_history_truncate(shl, zfs_read_history);
1421c891 179
d1261452 180 mutex_exit(&shl->procfs_list.pl_lock);
1421c891
PS
181}
182
0b1401ee
BB
183/*
184 * ==========================================================================
185 * SPA TXG History Routines
186 * ==========================================================================
187 */
188
189/*
190 * Txg statistics - Information exported regarding each txg sync
191 */
192
193typedef struct spa_txg_history {
194 uint64_t txg; /* txg id */
195 txg_state_t state; /* active txg state */
196 uint64_t nread; /* number of bytes read */
197 uint64_t nwritten; /* number of bytes written */
198 uint64_t reads; /* number of read operations */
199 uint64_t writes; /* number of write operations */
3ccab252 200 uint64_t ndirty; /* number of dirty bytes */
0b1401ee 201 hrtime_t times[TXG_STATE_COMMITTED]; /* completion times */
d1261452 202 procfs_list_node_t sth_node;
0b1401ee
BB
203} spa_txg_history_t;
204
205static int
d1261452 206spa_txg_history_show_header(struct seq_file *f)
0b1401ee 207{
d1261452 208 seq_printf(f, "%-8s %-16s %-5s %-12s %-12s %-12s "
478d64fd 209 "%-8s %-8s %-12s %-12s %-12s %-12s\n", "txg", "birth", "state",
3ccab252 210 "ndirty", "nread", "nwritten", "reads", "writes",
478d64fd 211 "otime", "qtime", "wtime", "stime");
0b1401ee
BB
212 return (0);
213}
214
215static int
d1261452 216spa_txg_history_show(struct seq_file *f, void *data)
0b1401ee
BB
217{
218 spa_txg_history_t *sth = (spa_txg_history_t *)data;
478d64fd 219 uint64_t open = 0, quiesce = 0, wait = 0, sync = 0;
0b1401ee
BB
220 char state;
221
222 switch (sth->state) {
223 case TXG_STATE_BIRTH: state = 'B'; break;
224 case TXG_STATE_OPEN: state = 'O'; break;
225 case TXG_STATE_QUIESCED: state = 'Q'; break;
478d64fd 226 case TXG_STATE_WAIT_FOR_SYNC: state = 'W'; break;
0b1401ee
BB
227 case TXG_STATE_SYNCED: state = 'S'; break;
228 case TXG_STATE_COMMITTED: state = 'C'; break;
229 default: state = '?'; break;
230 }
231
232 if (sth->times[TXG_STATE_OPEN])
233 open = sth->times[TXG_STATE_OPEN] -
234 sth->times[TXG_STATE_BIRTH];
235
236 if (sth->times[TXG_STATE_QUIESCED])
237 quiesce = sth->times[TXG_STATE_QUIESCED] -
238 sth->times[TXG_STATE_OPEN];
239
478d64fd
IL
240 if (sth->times[TXG_STATE_WAIT_FOR_SYNC])
241 wait = sth->times[TXG_STATE_WAIT_FOR_SYNC] -
242 sth->times[TXG_STATE_QUIESCED];
243
0b1401ee
BB
244 if (sth->times[TXG_STATE_SYNCED])
245 sync = sth->times[TXG_STATE_SYNCED] -
478d64fd 246 sth->times[TXG_STATE_WAIT_FOR_SYNC];
0b1401ee 247
d1261452 248 seq_printf(f, "%-8llu %-16llu %-5c %-12llu "
478d64fd 249 "%-12llu %-12llu %-8llu %-8llu %-12llu %-12llu %-12llu %-12llu\n",
0b1401ee 250 (longlong_t)sth->txg, sth->times[TXG_STATE_BIRTH], state,
3ccab252 251 (u_longlong_t)sth->ndirty,
0b1401ee
BB
252 (u_longlong_t)sth->nread, (u_longlong_t)sth->nwritten,
253 (u_longlong_t)sth->reads, (u_longlong_t)sth->writes,
478d64fd
IL
254 (u_longlong_t)open, (u_longlong_t)quiesce, (u_longlong_t)wait,
255 (u_longlong_t)sync);
0b1401ee
BB
256
257 return (0);
258}
259
d1261452
JG
260/* Remove oldest elements from list until there are no more than 'size' left */
261static void
262spa_txg_history_truncate(spa_history_list_t *shl, unsigned int size)
0b1401ee 263{
d1261452
JG
264 spa_txg_history_t *sth;
265 while (shl->size > size) {
266 sth = list_remove_head(&shl->procfs_list.pl_list);
267 ASSERT3P(sth, !=, NULL);
268 kmem_free(sth, sizeof (spa_txg_history_t));
269 shl->size--;
270 }
0b1401ee 271
d1261452
JG
272 if (size == 0)
273 ASSERT(list_is_empty(&shl->procfs_list.pl_list));
0b1401ee 274
0b1401ee
BB
275}
276
0b1401ee 277static int
d1261452 278spa_txg_history_clear(procfs_list_t *procfs_list)
0b1401ee 279{
d1261452
JG
280 spa_history_list_t *shl = procfs_list->pl_private;
281 mutex_enter(&procfs_list->pl_lock);
282 spa_txg_history_truncate(shl, 0);
283 mutex_exit(&procfs_list->pl_lock);
0b1401ee
BB
284 return (0);
285}
286
287static void
288spa_txg_history_init(spa_t *spa)
289{
d1261452 290 spa_history_list_t *shl = &spa->spa_stats.txg_history;
0b1401ee 291
d1261452 292 shl->size = 0;
d1261452 293 shl->procfs_list.pl_private = shl;
7b8363d7
MM
294 procfs_list_install("zfs",
295 spa_name(spa),
d1261452 296 "txgs",
a887d653 297 0644,
d1261452
JG
298 &shl->procfs_list,
299 spa_txg_history_show,
300 spa_txg_history_show_header,
301 spa_txg_history_clear,
302 offsetof(spa_txg_history_t, sth_node));
0b1401ee
BB
303}
304
305static void
306spa_txg_history_destroy(spa_t *spa)
307{
d1261452
JG
308 spa_history_list_t *shl = &spa->spa_stats.txg_history;
309 procfs_list_uninstall(&shl->procfs_list);
310 spa_txg_history_truncate(shl, 0);
311 procfs_list_destroy(&shl->procfs_list);
0b1401ee
BB
312}
313
314/*
315 * Add a new txg to historical record.
316 */
317void
01b738f4 318spa_txg_history_add(spa_t *spa, uint64_t txg, hrtime_t birth_time)
0b1401ee 319{
d1261452
JG
320 spa_history_list_t *shl = &spa->spa_stats.txg_history;
321 spa_txg_history_t *sth;
0b1401ee 322
d1261452 323 if (zfs_txg_history == 0 && shl->size == 0)
0b1401ee
BB
324 return;
325
79c76d5b 326 sth = kmem_zalloc(sizeof (spa_txg_history_t), KM_SLEEP);
0b1401ee
BB
327 sth->txg = txg;
328 sth->state = TXG_STATE_OPEN;
01b738f4 329 sth->times[TXG_STATE_BIRTH] = birth_time;
0b1401ee 330
d1261452
JG
331 mutex_enter(&shl->procfs_list.pl_lock);
332 procfs_list_add(&shl->procfs_list, sth);
333 shl->size++;
334 spa_txg_history_truncate(shl, zfs_txg_history);
335 mutex_exit(&shl->procfs_list.pl_lock);
0b1401ee
BB
336}
337
338/*
339 * Set txg state completion time and increment current state.
340 */
341int
342spa_txg_history_set(spa_t *spa, uint64_t txg, txg_state_t completed_state,
343 hrtime_t completed_time)
344{
d1261452 345 spa_history_list_t *shl = &spa->spa_stats.txg_history;
0b1401ee
BB
346 spa_txg_history_t *sth;
347 int error = ENOENT;
348
349 if (zfs_txg_history == 0)
350 return (0);
351
d1261452
JG
352 mutex_enter(&shl->procfs_list.pl_lock);
353 for (sth = list_tail(&shl->procfs_list.pl_list); sth != NULL;
354 sth = list_prev(&shl->procfs_list.pl_list, sth)) {
0b1401ee
BB
355 if (sth->txg == txg) {
356 sth->times[completed_state] = completed_time;
357 sth->state++;
358 error = 0;
359 break;
360 }
361 }
d1261452 362 mutex_exit(&shl->procfs_list.pl_lock);
0b1401ee
BB
363
364 return (error);
365}
366
367/*
368 * Set txg IO stats.
369 */
baf67d15 370static int
0b1401ee 371spa_txg_history_set_io(spa_t *spa, uint64_t txg, uint64_t nread,
3ccab252 372 uint64_t nwritten, uint64_t reads, uint64_t writes, uint64_t ndirty)
0b1401ee 373{
d1261452 374 spa_history_list_t *shl = &spa->spa_stats.txg_history;
0b1401ee
BB
375 spa_txg_history_t *sth;
376 int error = ENOENT;
377
378 if (zfs_txg_history == 0)
379 return (0);
380
d1261452
JG
381 mutex_enter(&shl->procfs_list.pl_lock);
382 for (sth = list_tail(&shl->procfs_list.pl_list); sth != NULL;
383 sth = list_prev(&shl->procfs_list.pl_list, sth)) {
0b1401ee
BB
384 if (sth->txg == txg) {
385 sth->nread = nread;
386 sth->nwritten = nwritten;
387 sth->reads = reads;
388 sth->writes = writes;
3ccab252 389 sth->ndirty = ndirty;
0b1401ee
BB
390 error = 0;
391 break;
392 }
393 }
d1261452 394 mutex_exit(&shl->procfs_list.pl_lock);
0b1401ee
BB
395
396 return (error);
397}
398
baf67d15
BB
399txg_stat_t *
400spa_txg_history_init_io(spa_t *spa, uint64_t txg, dsl_pool_t *dp)
401{
402 txg_stat_t *ts;
403
404 if (zfs_txg_history == 0)
405 return (NULL);
406
407 ts = kmem_alloc(sizeof (txg_stat_t), KM_SLEEP);
408
6af7ba41 409 spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
baf67d15 410 vdev_get_stats(spa->spa_root_vdev, &ts->vs1);
6af7ba41 411 spa_config_exit(spa, SCL_CONFIG, FTAG);
baf67d15
BB
412
413 ts->txg = txg;
414 ts->ndirty = dp->dp_dirty_pertxg[txg & TXG_MASK];
415
416 spa_txg_history_set(spa, txg, TXG_STATE_WAIT_FOR_SYNC, gethrtime());
417
418 return (ts);
419}
420
421void
422spa_txg_history_fini_io(spa_t *spa, txg_stat_t *ts)
423{
424 if (ts == NULL)
425 return;
426
427 if (zfs_txg_history == 0) {
428 kmem_free(ts, sizeof (txg_stat_t));
429 return;
430 }
431
6af7ba41 432 spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
baf67d15 433 vdev_get_stats(spa->spa_root_vdev, &ts->vs2);
6af7ba41 434 spa_config_exit(spa, SCL_CONFIG, FTAG);
baf67d15
BB
435
436 spa_txg_history_set(spa, ts->txg, TXG_STATE_SYNCED, gethrtime());
437 spa_txg_history_set_io(spa, ts->txg,
438 ts->vs2.vs_bytes[ZIO_TYPE_READ] - ts->vs1.vs_bytes[ZIO_TYPE_READ],
439 ts->vs2.vs_bytes[ZIO_TYPE_WRITE] - ts->vs1.vs_bytes[ZIO_TYPE_WRITE],
440 ts->vs2.vs_ops[ZIO_TYPE_READ] - ts->vs1.vs_ops[ZIO_TYPE_READ],
441 ts->vs2.vs_ops[ZIO_TYPE_WRITE] - ts->vs1.vs_ops[ZIO_TYPE_WRITE],
442 ts->ndirty);
443
444 kmem_free(ts, sizeof (txg_stat_t));
445}
446
2d37239a
BB
447/*
448 * ==========================================================================
449 * SPA TX Assign Histogram Routines
450 * ==========================================================================
451 */
452
453/*
454 * Tx statistics - Information exported regarding dmu_tx_assign time.
455 */
456
457/*
458 * When the kstat is written zero all buckets. When the kstat is read
459 * count the number of trailing buckets set to zero and update ks_ndata
460 * such that they are not output.
461 */
462static int
463spa_tx_assign_update(kstat_t *ksp, int rw)
464{
465 spa_t *spa = ksp->ks_private;
d1261452 466 spa_history_kstat_t *shk = &spa->spa_stats.tx_assign_histogram;
2d37239a
BB
467 int i;
468
469 if (rw == KSTAT_WRITE) {
d1261452 470 for (i = 0; i < shk->count; i++)
60265072 471 ((kstat_named_t *)shk->priv)[i].value.ui64 = 0;
2d37239a
BB
472 }
473
d1261452 474 for (i = shk->count; i > 0; i--)
60265072 475 if (((kstat_named_t *)shk->priv)[i-1].value.ui64 != 0)
2d37239a
BB
476 break;
477
478 ksp->ks_ndata = i;
d1d7e268 479 ksp->ks_data_size = i * sizeof (kstat_named_t);
2d37239a
BB
480
481 return (0);
482}
483
484static void
485spa_tx_assign_init(spa_t *spa)
486{
d1261452 487 spa_history_kstat_t *shk = &spa->spa_stats.tx_assign_histogram;
761b8ec6 488 char *name;
2d37239a
BB
489 kstat_named_t *ks;
490 kstat_t *ksp;
491 int i;
492
d1261452 493 mutex_init(&shk->lock, NULL, MUTEX_DEFAULT, NULL);
2d37239a 494
d1261452
JG
495 shk->count = 42; /* power of two buckets for 1ns to 2,199s */
496 shk->size = shk->count * sizeof (kstat_named_t);
60265072 497 shk->priv = kmem_alloc(shk->size, KM_SLEEP);
2d37239a 498
761b8ec6 499 name = kmem_asprintf("zfs/%s", spa_name(spa));
2d37239a 500
d1261452 501 for (i = 0; i < shk->count; i++) {
60265072 502 ks = &((kstat_named_t *)shk->priv)[i];
2d37239a
BB
503 ks->data_type = KSTAT_DATA_UINT64;
504 ks->value.ui64 = 0;
505 (void) snprintf(ks->name, KSTAT_STRLEN, "%llu ns",
506 (u_longlong_t)1 << i);
507 }
508
509 ksp = kstat_create(name, 0, "dmu_tx_assign", "misc",
510 KSTAT_TYPE_NAMED, 0, KSTAT_FLAG_VIRTUAL);
d1261452 511 shk->kstat = ksp;
2d37239a
BB
512
513 if (ksp) {
d1261452 514 ksp->ks_lock = &shk->lock;
60265072 515 ksp->ks_data = shk->priv;
d1261452
JG
516 ksp->ks_ndata = shk->count;
517 ksp->ks_data_size = shk->size;
2d37239a
BB
518 ksp->ks_private = spa;
519 ksp->ks_update = spa_tx_assign_update;
520 kstat_install(ksp);
521 }
e4f5fa12 522 kmem_strfree(name);
2d37239a
BB
523}
524
525static void
526spa_tx_assign_destroy(spa_t *spa)
527{
d1261452 528 spa_history_kstat_t *shk = &spa->spa_stats.tx_assign_histogram;
2d37239a
BB
529 kstat_t *ksp;
530
d1261452 531 ksp = shk->kstat;
2d37239a
BB
532 if (ksp)
533 kstat_delete(ksp);
534
60265072 535 kmem_free(shk->priv, shk->size);
d1261452 536 mutex_destroy(&shk->lock);
2d37239a
BB
537}
538
539void
540spa_tx_assign_add_nsecs(spa_t *spa, uint64_t nsecs)
541{
d1261452 542 spa_history_kstat_t *shk = &spa->spa_stats.tx_assign_histogram;
2d37239a
BB
543 uint64_t idx = 0;
544
d1261452 545 while (((1ULL << idx) < nsecs) && (idx < shk->size - 1))
2d37239a
BB
546 idx++;
547
60265072 548 atomic_inc_64(&((kstat_named_t *)shk->priv)[idx].value.ui64);
2d37239a
BB
549}
550
379ca9cf
OF
551/*
552 * ==========================================================================
553 * SPA MMP History Routines
554 * ==========================================================================
555 */
556
557/*
d2160d05
OF
558 * MMP statistics - Information exported regarding attempted MMP writes
559 * For MMP writes issued, fields used as per comments below.
560 * For MMP writes skipped, an entry represents a span of time when
561 * writes were skipped for same reason (error from mmp_random_leaf).
562 * Differences are:
563 * timestamp time first write skipped, if >1 skipped in a row
564 * mmp_delay delay value at timestamp
565 * vdev_guid number of writes skipped
566 * io_error one of enum mmp_error
567 * duration time span (ns) of skipped writes
379ca9cf
OF
568 */
569
570typedef struct spa_mmp_history {
d1261452 571 uint64_t mmp_node_id; /* unique # for updates */
379ca9cf 572 uint64_t txg; /* txg of last sync */
d2160d05
OF
573 uint64_t timestamp; /* UTC time MMP write issued */
574 uint64_t mmp_delay; /* mmp_thread.mmp_delay at timestamp */
379ca9cf
OF
575 uint64_t vdev_guid; /* unique ID of leaf vdev */
576 char *vdev_path;
d2160d05 577 int vdev_label; /* vdev label */
7088545d 578 int io_error; /* error status of MMP write */
d2160d05 579 hrtime_t error_start; /* hrtime of start of error period */
7088545d 580 hrtime_t duration; /* time from submission to completion */
d1261452 581 procfs_list_node_t smh_node;
379ca9cf
OF
582} spa_mmp_history_t;
583
584static int
d1261452 585spa_mmp_history_show_header(struct seq_file *f)
379ca9cf 586{
d1261452 587 seq_printf(f, "%-10s %-10s %-10s %-6s %-10s %-12s %-24s "
7088545d
OF
588 "%-10s %s\n", "id", "txg", "timestamp", "error", "duration",
589 "mmp_delay", "vdev_guid", "vdev_label", "vdev_path");
379ca9cf
OF
590 return (0);
591}
592
593static int
d1261452 594spa_mmp_history_show(struct seq_file *f, void *data)
379ca9cf
OF
595{
596 spa_mmp_history_t *smh = (spa_mmp_history_t *)data;
d2160d05
OF
597 char skip_fmt[] = "%-10llu %-10llu %10llu %#6llx %10lld %12llu %-24llu "
598 "%-10lld %s\n";
599 char write_fmt[] = "%-10llu %-10llu %10llu %6lld %10lld %12llu %-24llu "
600 "%-10lld %s\n";
379ca9cf 601
d1261452
JG
602 seq_printf(f, (smh->error_start ? skip_fmt : write_fmt),
603 (u_longlong_t)smh->mmp_node_id, (u_longlong_t)smh->txg,
7088545d
OF
604 (u_longlong_t)smh->timestamp, (longlong_t)smh->io_error,
605 (longlong_t)smh->duration, (u_longlong_t)smh->mmp_delay,
606 (u_longlong_t)smh->vdev_guid, (u_longlong_t)smh->vdev_label,
379ca9cf
OF
607 (smh->vdev_path ? smh->vdev_path : "-"));
608
609 return (0);
610}
611
d1261452
JG
612/* Remove oldest elements from list until there are no more than 'size' left */
613static void
614spa_mmp_history_truncate(spa_history_list_t *shl, unsigned int size)
379ca9cf 615{
d1261452
JG
616 spa_mmp_history_t *smh;
617 while (shl->size > size) {
618 smh = list_remove_head(&shl->procfs_list.pl_list);
619 if (smh->vdev_path)
e4f5fa12 620 kmem_strfree(smh->vdev_path);
d1261452
JG
621 kmem_free(smh, sizeof (spa_mmp_history_t));
622 shl->size--;
623 }
379ca9cf 624
d1261452
JG
625 if (size == 0)
626 ASSERT(list_is_empty(&shl->procfs_list.pl_list));
379ca9cf 627
379ca9cf
OF
628}
629
379ca9cf 630static int
d1261452 631spa_mmp_history_clear(procfs_list_t *procfs_list)
379ca9cf 632{
d1261452
JG
633 spa_history_list_t *shl = procfs_list->pl_private;
634 mutex_enter(&procfs_list->pl_lock);
635 spa_mmp_history_truncate(shl, 0);
636 mutex_exit(&procfs_list->pl_lock);
379ca9cf
OF
637 return (0);
638}
639
640static void
641spa_mmp_history_init(spa_t *spa)
642{
d1261452 643 spa_history_list_t *shl = &spa->spa_stats.mmp_history;
379ca9cf 644
d1261452 645 shl->size = 0;
379ca9cf 646
d1261452 647 shl->procfs_list.pl_private = shl;
7b8363d7
MM
648 procfs_list_install("zfs",
649 spa_name(spa),
d1261452 650 "multihost",
a887d653 651 0644,
d1261452
JG
652 &shl->procfs_list,
653 spa_mmp_history_show,
654 spa_mmp_history_show_header,
655 spa_mmp_history_clear,
656 offsetof(spa_mmp_history_t, smh_node));
379ca9cf
OF
657}
658
659static void
660spa_mmp_history_destroy(spa_t *spa)
661{
d1261452
JG
662 spa_history_list_t *shl = &spa->spa_stats.mmp_history;
663 procfs_list_uninstall(&shl->procfs_list);
664 spa_mmp_history_truncate(shl, 0);
665 procfs_list_destroy(&shl->procfs_list);
379ca9cf
OF
666}
667
d2160d05
OF
668/*
669 * Set duration in existing "skip" record to how long we have waited for a leaf
670 * vdev to become available.
671 *
d1261452 672 * Important that we start search at the tail of the list where new
d2160d05
OF
673 * records are inserted, so this is normally an O(1) operation.
674 */
675int
d1261452 676spa_mmp_history_set_skip(spa_t *spa, uint64_t mmp_node_id)
d2160d05 677{
d1261452 678 spa_history_list_t *shl = &spa->spa_stats.mmp_history;
d2160d05
OF
679 spa_mmp_history_t *smh;
680 int error = ENOENT;
681
d1261452 682 if (zfs_multihost_history == 0 && shl->size == 0)
d2160d05
OF
683 return (0);
684
d1261452
JG
685 mutex_enter(&shl->procfs_list.pl_lock);
686 for (smh = list_tail(&shl->procfs_list.pl_list); smh != NULL;
687 smh = list_prev(&shl->procfs_list.pl_list, smh)) {
688 if (smh->mmp_node_id == mmp_node_id) {
d2160d05
OF
689 ASSERT3U(smh->io_error, !=, 0);
690 smh->duration = gethrtime() - smh->error_start;
691 smh->vdev_guid++;
692 error = 0;
693 break;
694 }
695 }
d1261452 696 mutex_exit(&shl->procfs_list.pl_lock);
d2160d05
OF
697
698 return (error);
699}
700
379ca9cf 701/*
7088545d 702 * Set MMP write duration and error status in existing record.
d2160d05 703 * See comment re: search order above spa_mmp_history_set_skip().
7088545d
OF
704 */
705int
d1261452 706spa_mmp_history_set(spa_t *spa, uint64_t mmp_node_id, int io_error,
7088545d
OF
707 hrtime_t duration)
708{
d1261452 709 spa_history_list_t *shl = &spa->spa_stats.mmp_history;
7088545d
OF
710 spa_mmp_history_t *smh;
711 int error = ENOENT;
712
d1261452 713 if (zfs_multihost_history == 0 && shl->size == 0)
7088545d
OF
714 return (0);
715
d1261452
JG
716 mutex_enter(&shl->procfs_list.pl_lock);
717 for (smh = list_tail(&shl->procfs_list.pl_list); smh != NULL;
718 smh = list_prev(&shl->procfs_list.pl_list, smh)) {
719 if (smh->mmp_node_id == mmp_node_id) {
d2160d05 720 ASSERT(smh->io_error == 0);
7088545d
OF
721 smh->io_error = io_error;
722 smh->duration = duration;
723 error = 0;
724 break;
725 }
726 }
d1261452 727 mutex_exit(&shl->procfs_list.pl_lock);
7088545d
OF
728
729 return (error);
730}
731
732/*
d2160d05
OF
733 * Add a new MMP historical record.
734 * error == 0 : a write was issued.
735 * error != 0 : a write was not issued because no leaves were found.
379ca9cf 736 */
d1261452 737void
d2160d05 738spa_mmp_history_add(spa_t *spa, uint64_t txg, uint64_t timestamp,
d1261452 739 uint64_t mmp_delay, vdev_t *vd, int label, uint64_t mmp_node_id,
d2160d05 740 int error)
379ca9cf 741{
d1261452
JG
742 spa_history_list_t *shl = &spa->spa_stats.mmp_history;
743 spa_mmp_history_t *smh;
379ca9cf 744
d1261452
JG
745 if (zfs_multihost_history == 0 && shl->size == 0)
746 return;
379ca9cf
OF
747
748 smh = kmem_zalloc(sizeof (spa_mmp_history_t), KM_SLEEP);
749 smh->txg = txg;
750 smh->timestamp = timestamp;
751 smh->mmp_delay = mmp_delay;
d2160d05
OF
752 if (vd) {
753 smh->vdev_guid = vd->vdev_guid;
754 if (vd->vdev_path)
e4f5fa12 755 smh->vdev_path = kmem_strdup(vd->vdev_path);
d2160d05 756 }
379ca9cf 757 smh->vdev_label = label;
d1261452 758 smh->mmp_node_id = mmp_node_id;
379ca9cf 759
d2160d05
OF
760 if (error) {
761 smh->io_error = error;
762 smh->error_start = gethrtime();
763 smh->vdev_guid = 1;
764 }
765
d1261452
JG
766 mutex_enter(&shl->procfs_list.pl_lock);
767 procfs_list_add(&shl->procfs_list, smh);
768 shl->size++;
769 spa_mmp_history_truncate(shl, zfs_multihost_history);
770 mutex_exit(&shl->procfs_list.pl_lock);
379ca9cf
OF
771}
772
f0ed6c74
TH
773static void *
774spa_state_addr(kstat_t *ksp, loff_t n)
775{
e84e4921
MM
776 if (n == 0)
777 return (ksp->ks_private); /* return the spa_t */
778 return (NULL);
f0ed6c74
TH
779}
780
781static int
782spa_state_data(char *buf, size_t size, void *data)
783{
784 spa_t *spa = (spa_t *)data;
785 (void) snprintf(buf, size, "%s\n", spa_state_to_name(spa));
786 return (0);
787}
788
789/*
790 * Return the state of the pool in /proc/spl/kstat/zfs/<pool>/state.
791 *
792 * This is a lock-less read of the pool's state (unlike using 'zpool', which
793 * can potentially block for seconds). Because it doesn't block, it can useful
794 * as a pool heartbeat value.
795 */
796static void
797spa_state_init(spa_t *spa)
798{
d1261452 799 spa_history_kstat_t *shk = &spa->spa_stats.state;
f0ed6c74
TH
800 char *name;
801 kstat_t *ksp;
802
d1261452 803 mutex_init(&shk->lock, NULL, MUTEX_DEFAULT, NULL);
f0ed6c74
TH
804
805 name = kmem_asprintf("zfs/%s", spa_name(spa));
806 ksp = kstat_create(name, 0, "state", "misc",
807 KSTAT_TYPE_RAW, 0, KSTAT_FLAG_VIRTUAL);
808
d1261452 809 shk->kstat = ksp;
f0ed6c74 810 if (ksp) {
d1261452 811 ksp->ks_lock = &shk->lock;
f0ed6c74
TH
812 ksp->ks_data = NULL;
813 ksp->ks_private = spa;
814 ksp->ks_flags |= KSTAT_FLAG_NO_HEADERS;
815 kstat_set_raw_ops(ksp, NULL, spa_state_data, spa_state_addr);
816 kstat_install(ksp);
817 }
818
e4f5fa12 819 kmem_strfree(name);
f0ed6c74
TH
820}
821
00ac7746
AW
822static int
823spa_guid_data(char *buf, size_t size, void *data)
824{
825 spa_t *spa = (spa_t *)data;
826 (void) snprintf(buf, size, "%llu\n", (u_longlong_t)spa_guid(spa));
827 return (0);
828}
829
830static void
831spa_guid_init(spa_t *spa)
832{
833 spa_history_kstat_t *shk = &spa->spa_stats.guid;
834 char *name;
835 kstat_t *ksp;
836
837 mutex_init(&shk->lock, NULL, MUTEX_DEFAULT, NULL);
838
839 name = kmem_asprintf("zfs/%s", spa_name(spa));
840
841 ksp = kstat_create(name, 0, "guid", "misc",
842 KSTAT_TYPE_RAW, 0, KSTAT_FLAG_VIRTUAL);
843
844 shk->kstat = ksp;
845 if (ksp) {
846 ksp->ks_lock = &shk->lock;
847 ksp->ks_data = NULL;
848 ksp->ks_private = spa;
849 ksp->ks_flags |= KSTAT_FLAG_NO_HEADERS;
850 kstat_set_raw_ops(ksp, NULL, spa_guid_data, spa_state_addr);
851 kstat_install(ksp);
852 }
853
854 kmem_strfree(name);
855}
856
f0ed6c74
TH
857static void
858spa_health_destroy(spa_t *spa)
859{
d1261452
JG
860 spa_history_kstat_t *shk = &spa->spa_stats.state;
861 kstat_t *ksp = shk->kstat;
f0ed6c74
TH
862 if (ksp)
863 kstat_delete(ksp);
864
d1261452 865 mutex_destroy(&shk->lock);
f0ed6c74
TH
866}
867
00ac7746
AW
868static void
869spa_guid_destroy(spa_t *spa)
870{
871 spa_history_kstat_t *shk = &spa->spa_stats.guid;
872 kstat_t *ksp = shk->kstat;
873 if (ksp)
874 kstat_delete(ksp);
875
876 mutex_destroy(&shk->lock);
877}
878
18168da7 879static const spa_iostats_t spa_iostats_template = {
1b939560
BB
880 { "trim_extents_written", KSTAT_DATA_UINT64 },
881 { "trim_bytes_written", KSTAT_DATA_UINT64 },
882 { "trim_extents_skipped", KSTAT_DATA_UINT64 },
883 { "trim_bytes_skipped", KSTAT_DATA_UINT64 },
884 { "trim_extents_failed", KSTAT_DATA_UINT64 },
885 { "trim_bytes_failed", KSTAT_DATA_UINT64 },
886 { "autotrim_extents_written", KSTAT_DATA_UINT64 },
887 { "autotrim_bytes_written", KSTAT_DATA_UINT64 },
888 { "autotrim_extents_skipped", KSTAT_DATA_UINT64 },
889 { "autotrim_bytes_skipped", KSTAT_DATA_UINT64 },
890 { "autotrim_extents_failed", KSTAT_DATA_UINT64 },
891 { "autotrim_bytes_failed", KSTAT_DATA_UINT64 },
b7654bd7
GA
892 { "simple_trim_extents_written", KSTAT_DATA_UINT64 },
893 { "simple_trim_bytes_written", KSTAT_DATA_UINT64 },
894 { "simple_trim_extents_skipped", KSTAT_DATA_UINT64 },
895 { "simple_trim_bytes_skipped", KSTAT_DATA_UINT64 },
896 { "simple_trim_extents_failed", KSTAT_DATA_UINT64 },
897 { "simple_trim_bytes_failed", KSTAT_DATA_UINT64 },
1b939560
BB
898};
899
900#define SPA_IOSTATS_ADD(stat, val) \
901 atomic_add_64(&iostats->stat.value.ui64, (val));
902
903void
904spa_iostats_trim_add(spa_t *spa, trim_type_t type,
905 uint64_t extents_written, uint64_t bytes_written,
906 uint64_t extents_skipped, uint64_t bytes_skipped,
907 uint64_t extents_failed, uint64_t bytes_failed)
908{
909 spa_history_kstat_t *shk = &spa->spa_stats.iostats;
910 kstat_t *ksp = shk->kstat;
911 spa_iostats_t *iostats;
912
913 if (ksp == NULL)
914 return;
915
916 iostats = ksp->ks_data;
917 if (type == TRIM_TYPE_MANUAL) {
918 SPA_IOSTATS_ADD(trim_extents_written, extents_written);
919 SPA_IOSTATS_ADD(trim_bytes_written, bytes_written);
920 SPA_IOSTATS_ADD(trim_extents_skipped, extents_skipped);
921 SPA_IOSTATS_ADD(trim_bytes_skipped, bytes_skipped);
922 SPA_IOSTATS_ADD(trim_extents_failed, extents_failed);
923 SPA_IOSTATS_ADD(trim_bytes_failed, bytes_failed);
b7654bd7 924 } else if (type == TRIM_TYPE_AUTO) {
1b939560
BB
925 SPA_IOSTATS_ADD(autotrim_extents_written, extents_written);
926 SPA_IOSTATS_ADD(autotrim_bytes_written, bytes_written);
927 SPA_IOSTATS_ADD(autotrim_extents_skipped, extents_skipped);
928 SPA_IOSTATS_ADD(autotrim_bytes_skipped, bytes_skipped);
929 SPA_IOSTATS_ADD(autotrim_extents_failed, extents_failed);
930 SPA_IOSTATS_ADD(autotrim_bytes_failed, bytes_failed);
b7654bd7
GA
931 } else {
932 SPA_IOSTATS_ADD(simple_trim_extents_written, extents_written);
933 SPA_IOSTATS_ADD(simple_trim_bytes_written, bytes_written);
934 SPA_IOSTATS_ADD(simple_trim_extents_skipped, extents_skipped);
935 SPA_IOSTATS_ADD(simple_trim_bytes_skipped, bytes_skipped);
936 SPA_IOSTATS_ADD(simple_trim_extents_failed, extents_failed);
937 SPA_IOSTATS_ADD(simple_trim_bytes_failed, bytes_failed);
1b939560
BB
938 }
939}
940
65c7cc49 941static int
1b939560
BB
942spa_iostats_update(kstat_t *ksp, int rw)
943{
944 if (rw == KSTAT_WRITE) {
945 memcpy(ksp->ks_data, &spa_iostats_template,
946 sizeof (spa_iostats_t));
947 }
948
949 return (0);
950}
951
952static void
953spa_iostats_init(spa_t *spa)
954{
955 spa_history_kstat_t *shk = &spa->spa_stats.iostats;
956
957 mutex_init(&shk->lock, NULL, MUTEX_DEFAULT, NULL);
958
959 char *name = kmem_asprintf("zfs/%s", spa_name(spa));
960 kstat_t *ksp = kstat_create(name, 0, "iostats", "misc",
961 KSTAT_TYPE_NAMED, sizeof (spa_iostats_t) / sizeof (kstat_named_t),
962 KSTAT_FLAG_VIRTUAL);
963
964 shk->kstat = ksp;
965 if (ksp) {
966 int size = sizeof (spa_iostats_t);
967 ksp->ks_lock = &shk->lock;
968 ksp->ks_private = spa;
969 ksp->ks_update = spa_iostats_update;
970 ksp->ks_data = kmem_alloc(size, KM_SLEEP);
971 memcpy(ksp->ks_data, &spa_iostats_template, size);
972 kstat_install(ksp);
973 }
974
e4f5fa12 975 kmem_strfree(name);
1b939560
BB
976}
977
978static void
979spa_iostats_destroy(spa_t *spa)
980{
981 spa_history_kstat_t *shk = &spa->spa_stats.iostats;
982 kstat_t *ksp = shk->kstat;
983 if (ksp) {
984 kmem_free(ksp->ks_data, sizeof (spa_iostats_t));
985 kstat_delete(ksp);
986 }
987
988 mutex_destroy(&shk->lock);
989}
990
1421c891
PS
991void
992spa_stats_init(spa_t *spa)
993{
994 spa_read_history_init(spa);
0b1401ee 995 spa_txg_history_init(spa);
2d37239a 996 spa_tx_assign_init(spa);
379ca9cf 997 spa_mmp_history_init(spa);
f0ed6c74 998 spa_state_init(spa);
00ac7746 999 spa_guid_init(spa);
1b939560 1000 spa_iostats_init(spa);
1421c891
PS
1001}
1002
1003void
1004spa_stats_destroy(spa_t *spa)
1005{
1b939560 1006 spa_iostats_destroy(spa);
f0ed6c74 1007 spa_health_destroy(spa);
2d37239a 1008 spa_tx_assign_destroy(spa);
0b1401ee 1009 spa_txg_history_destroy(spa);
1421c891 1010 spa_read_history_destroy(spa);
379ca9cf 1011 spa_mmp_history_destroy(spa);
00ac7746 1012 spa_guid_destroy(spa);
1421c891
PS
1013}
1014
fdc2d303 1015ZFS_MODULE_PARAM(zfs, zfs_, read_history, UINT, ZMOD_RW,
7ada752a 1016 "Historical statistics for the last N reads");
964791ac
RM
1017
1018ZFS_MODULE_PARAM(zfs, zfs_, read_history_hits, INT, ZMOD_RW,
7ada752a 1019 "Include cache hits in read history");
964791ac 1020
fdc2d303 1021ZFS_MODULE_PARAM(zfs_txg, zfs_txg_, history, UINT, ZMOD_RW,
7ada752a 1022 "Historical statistics for the last N txgs");
964791ac 1023
fdc2d303 1024ZFS_MODULE_PARAM(zfs_multihost, zfs_multihost_, history, UINT, ZMOD_RW,
7ada752a 1025 "Historical statistics for last N multihost writes");