Skip to content

Commit a997c8c

Browse files
committed
zinject: count matches and injections for each handler
Sponsored-by: Klara, Inc. Sponsored-by: Wasabi Technology, Inc. Signed-off-by: Rob Norris <[email protected]>
1 parent b8e09c7 commit a997c8c

File tree

6 files changed

+221
-35
lines changed

6 files changed

+221
-35
lines changed

cmd/zinject/zinject.c

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
2323
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
2424
* Copyright (c) 2017, Intel Corporation.
25-
* Copyright (c) 2023-2024, Klara Inc.
25+
* Copyright (c) 2023-2025, Klara Inc.
2626
*/
2727

2828
/*
@@ -404,27 +404,30 @@ print_data_handler(int id, const char *pool, zinject_record_t *record,
404404

405405
if (*count == 0) {
406406
(void) printf("%3s %-15s %-6s %-6s %-8s %3s %-4s "
407-
"%-15s\n", "ID", "POOL", "OBJSET", "OBJECT", "TYPE",
408-
"LVL", "DVAs", "RANGE");
407+
"%-15s %-6s %-15s\n", "ID", "POOL", "OBJSET", "OBJECT",
408+
"TYPE", "LVL", "DVAs", "RANGE", "MATCH", "INJECT");
409409
(void) printf("--- --------------- ------ "
410-
"------ -------- --- ---- ---------------\n");
410+
"------ -------- --- ---- --------------- "
411+
"------ ------\n");
411412
}
412413

413414
*count += 1;
414415

415-
(void) printf("%3d %-15s %-6llu %-6llu %-8s %-3d 0x%02x ",
416-
id, pool, (u_longlong_t)record->zi_objset,
417-
(u_longlong_t)record->zi_object, type_to_name(record->zi_type),
418-
record->zi_level, record->zi_dvas);
419-
420-
421-
if (record->zi_start == 0 &&
422-
record->zi_end == -1ULL)
423-
(void) printf("all\n");
416+
char rangebuf[32];
417+
if (record->zi_start == 0 && record->zi_end == -1ULL)
418+
snprintf(rangebuf, sizeof (rangebuf), "all");
424419
else
425-
(void) printf("[%llu, %llu]\n", (u_longlong_t)record->zi_start,
420+
snprintf(rangebuf, sizeof (rangebuf), "[%llu, %llu]",
421+
(u_longlong_t)record->zi_start,
426422
(u_longlong_t)record->zi_end);
427423

424+
425+
(void) printf("%3d %-15s %-6llu %-6llu %-8s %-3d 0x%02x %-15s "
426+
"%6lu %6lu\n", id, pool, (u_longlong_t)record->zi_objset,
427+
(u_longlong_t)record->zi_object, type_to_name(record->zi_type),
428+
record->zi_level, record->zi_dvas, rangebuf,
429+
record->zi_match_count, record->zi_inject_count);
430+
428431
return (0);
429432
}
430433

@@ -445,21 +448,25 @@ print_device_handler(int id, const char *pool, zinject_record_t *record,
445448
return (0);
446449

447450
if (*count == 0) {
448-
(void) printf("%3s %-15s %-16s %-5s %-10s %-9s\n",
449-
"ID", "POOL", "GUID", "TYPE", "ERROR", "FREQ");
451+
(void) printf("%3s %-15s %-16s %-5s %-10s %-9s "
452+
"%-6s %-6s\n",
453+
"ID", "POOL", "GUID", "TYPE", "ERROR", "FREQ",
454+
"MATCH", "INJECT");
450455
(void) printf(
451456
"--- --------------- ---------------- "
452-
"----- ---------- ---------\n");
457+
"----- ---------- --------- "
458+
"------ ------\n");
453459
}
454460

455461
*count += 1;
456462

457463
double freq = record->zi_freq == 0 ? 100.0f :
458464
(((double)record->zi_freq) / ZI_PERCENTAGE_MAX) * 100.0f;
459465

460-
(void) printf("%3d %-15s %llx %-5s %-10s %8.4f%%\n", id, pool,
461-
(u_longlong_t)record->zi_guid, iotypestr[record->zi_iotype],
462-
err_to_str(record->zi_error), freq);
466+
(void) printf("%3d %-15s %llx %-5s %-10s %8.4f%% "
467+
"%6lu %6lu\n", id, pool, (u_longlong_t)record->zi_guid,
468+
iotypestr[record->zi_iotype], err_to_str(record->zi_error),
469+
freq, record->zi_match_count, record->zi_inject_count);
463470

464471
return (0);
465472
}
@@ -477,18 +484,19 @@ print_delay_handler(int id, const char *pool, zinject_record_t *record,
477484
return (0);
478485

479486
if (*count == 0) {
480-
(void) printf("%3s %-15s %-15s %-15s %s\n",
481-
"ID", "POOL", "DELAY (ms)", "LANES", "GUID");
487+
(void) printf("%3s %-15s %-15s %-15s %-16s %-6s\n",
488+
"ID", "POOL", "DELAY (ms)", "LANES", "GUID", "INJECT");
482489
(void) printf("--- --------------- --------------- "
483-
"--------------- ----------------\n");
490+
"--------------- ---------------- ------\n");
484491
}
485492

486493
*count += 1;
487494

488-
(void) printf("%3d %-15s %-15llu %-15llu %llx\n", id, pool,
495+
(void) printf("%3d %-15s %-15llu %-15llu %llx %6lu\n", id, pool,
489496
(u_longlong_t)NSEC2MSEC(record->zi_timer),
490497
(u_longlong_t)record->zi_nlanes,
491-
(u_longlong_t)record->zi_guid);
498+
(u_longlong_t)record->zi_guid,
499+
record->zi_inject_count);
492500

493501
return (0);
494502
}

include/sys/zfs_ioctl.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
* Copyright (c) 2012, 2024 by Delphix. All rights reserved.
2424
* Copyright 2016 RackTop Systems.
2525
* Copyright (c) 2017, Intel Corporation.
26-
* Copyright (c) 2024, Klara, Inc.
26+
* Copyright (c) 2024-2025, Klara, Inc.
2727
*/
2828

2929
#ifndef _SYS_ZFS_IOCTL_H
@@ -421,6 +421,8 @@ typedef struct zinject_record {
421421
uint64_t zi_nlanes;
422422
uint32_t zi_cmd;
423423
uint32_t zi_dvas;
424+
uint64_t zi_match_count; /* count of times matched */
425+
uint64_t zi_inject_count; /* count of times injected */
424426
} zinject_record_t;
425427

426428
#define ZINJECT_NULL 0x1

module/zfs/zio_inject.c

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
2323
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
2424
* Copyright (c) 2017, Intel Corporation.
25-
* Copyright (c) 2024, Klara Inc.
25+
* Copyright (c) 2024-2025, Klara Inc.
2626
*/
2727

2828
/*
@@ -129,6 +129,9 @@ static boolean_t
129129
zio_match_handler(const zbookmark_phys_t *zb, uint64_t type, int dva,
130130
zinject_record_t *record, int error)
131131
{
132+
boolean_t matched = B_FALSE;
133+
boolean_t injected = B_FALSE;
134+
132135
/*
133136
* Check for a match against the MOS, which is based on type
134137
*/
@@ -137,9 +140,8 @@ zio_match_handler(const zbookmark_phys_t *zb, uint64_t type, int dva,
137140
record->zi_object == DMU_META_DNODE_OBJECT) {
138141
if (record->zi_type == DMU_OT_NONE ||
139142
type == record->zi_type)
140-
return (freq_triggered(record->zi_freq));
141-
else
142-
return (B_FALSE);
143+
matched = B_TRUE;
144+
goto done;
143145
}
144146

145147
/*
@@ -153,10 +155,20 @@ zio_match_handler(const zbookmark_phys_t *zb, uint64_t type, int dva,
153155
(record->zi_dvas == 0 ||
154156
(dva != ZI_NO_DVA && (record->zi_dvas & (1ULL << dva)))) &&
155157
error == record->zi_error) {
156-
return (freq_triggered(record->zi_freq));
158+
matched = B_TRUE;
159+
goto done;
160+
}
161+
162+
done:
163+
if (matched) {
164+
record->zi_match_count++;
165+
injected = freq_triggered(record->zi_freq);
157166
}
158167

159-
return (B_FALSE);
168+
if (injected)
169+
record->zi_inject_count++;
170+
171+
return (injected);
160172
}
161173

162174
/*
@@ -177,8 +189,11 @@ zio_handle_panic_injection(spa_t *spa, const char *tag, uint64_t type)
177189
continue;
178190

179191
if (handler->zi_record.zi_type == type &&
180-
strcmp(tag, handler->zi_record.zi_func) == 0)
192+
strcmp(tag, handler->zi_record.zi_func) == 0) {
193+
handler->zi_record.zi_match_count++;
194+
handler->zi_record.zi_inject_count++;
181195
panic("Panic requested in function %s\n", tag);
196+
}
182197
}
183198

184199
rw_exit(&inject_lock);
@@ -336,6 +351,8 @@ zio_handle_label_injection(zio_t *zio, int error)
336351

337352
if (zio->io_vd->vdev_guid == handler->zi_record.zi_guid &&
338353
(offset >= start && offset <= end)) {
354+
handler->zi_record.zi_match_count++;
355+
handler->zi_record.zi_inject_count++;
339356
ret = error;
340357
break;
341358
}
@@ -400,12 +417,16 @@ zio_handle_device_injection_impl(vdev_t *vd, zio_t *zio, int err1, int err2)
400417

401418
if (handler->zi_record.zi_error == err1 ||
402419
handler->zi_record.zi_error == err2) {
420+
handler->zi_record.zi_match_count++;
421+
403422
/*
404423
* limit error injection if requested
405424
*/
406425
if (!freq_triggered(handler->zi_record.zi_freq))
407426
continue;
408427

428+
handler->zi_record.zi_inject_count++;
429+
409430
/*
410431
* For a failed open, pretend like the device
411432
* has gone away.
@@ -441,6 +462,8 @@ zio_handle_device_injection_impl(vdev_t *vd, zio_t *zio, int err1, int err2)
441462
break;
442463
}
443464
if (handler->zi_record.zi_error == ENXIO) {
465+
handler->zi_record.zi_match_count++;
466+
handler->zi_record.zi_inject_count++;
444467
ret = SET_ERROR(EIO);
445468
break;
446469
}
@@ -483,6 +506,8 @@ zio_handle_ignored_writes(zio_t *zio)
483506
handler->zi_record.zi_cmd != ZINJECT_IGNORED_WRITES)
484507
continue;
485508

509+
handler->zi_record.zi_match_count++;
510+
486511
/*
487512
* Positive duration implies # of seconds, negative
488513
* a number of txgs
@@ -495,8 +520,10 @@ zio_handle_ignored_writes(zio_t *zio)
495520
}
496521

497522
/* Have a "problem" writing 60% of the time */
498-
if (random_in_range(100) < 60)
523+
if (random_in_range(100) < 60) {
524+
handler->zi_record.zi_inject_count++;
499525
zio->io_pipeline &= ~ZIO_VDEV_IO_STAGES;
526+
}
500527
break;
501528
}
502529

@@ -520,6 +547,9 @@ spa_handle_ignored_writes(spa_t *spa)
520547
handler->zi_record.zi_cmd != ZINJECT_IGNORED_WRITES)
521548
continue;
522549

550+
handler->zi_record.zi_match_count++;
551+
handler->zi_record.zi_inject_count++;
552+
523553
if (handler->zi_record.zi_duration > 0) {
524554
VERIFY(handler->zi_record.zi_timer == 0 ||
525555
ddi_time_after64(
@@ -699,6 +729,10 @@ zio_handle_io_delay(zio_t *zio)
699729
*/
700730
min_handler->zi_next_lane = (min_handler->zi_next_lane + 1) %
701731
min_handler->zi_record.zi_nlanes;
732+
733+
min_handler->zi_record.zi_match_count++;
734+
min_handler->zi_record.zi_inject_count++;
735+
702736
}
703737

704738
mutex_exit(&inject_delay_mtx);
@@ -721,9 +755,11 @@ zio_handle_pool_delay(spa_t *spa, hrtime_t elapsed, zinject_type_t command)
721755
handler = list_next(&inject_handlers, handler)) {
722756
ASSERT3P(handler->zi_spa_name, !=, NULL);
723757
if (strcmp(spa_name(spa), handler->zi_spa_name) == 0) {
758+
handler->zi_record.zi_match_count++;
724759
uint64_t pause =
725760
SEC2NSEC(handler->zi_record.zi_duration);
726761
if (pause > elapsed) {
762+
handler->zi_record.zi_inject_count++;
727763
delay = pause - elapsed;
728764
}
729765
id = handler->zi_id;

tests/runfiles/common.run

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ tests = ['json_sanity']
159159
tags = ['functional', 'cli_root', 'json']
160160

161161
[tests/functional/cli_root/zinject]
162-
tests = ['zinject_args']
162+
tests = ['zinject_args', 'zinject_counts']
163163
pre =
164164
post =
165165
tags = ['functional', 'cli_root', 'zinject']

tests/zfs-tests/tests/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
615615
functional/cli_root/json/setup.ksh \
616616
functional/cli_root/json/json_sanity.ksh \
617617
functional/cli_root/zinject/zinject_args.ksh \
618+
functional/cli_root/zinject/zinject_counts.ksh \
618619
functional/cli_root/zdb/zdb_002_pos.ksh \
619620
functional/cli_root/zdb/zdb_003_pos.ksh \
620621
functional/cli_root/zdb/zdb_004_pos.ksh \

0 commit comments

Comments
 (0)