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