Skip to content

Commit c1bc99e

Browse files
robnPaul Dagnelie
authored andcommitted
zinject: add "probe" device injection type
Injecting a device probe failure is not possible by matching IO types, because probe IO goes to the label regions, which is explicitly excluded from injection. Even if it were possible, it would be awkward to do, because a probe is sequence of reads and writes. This commit adds a new IO "type" to match for injection, which looks for the ZIO_FLAG_PROBE flag instead. Any probe IO will be match the injection record and recieve the wanted error. Sponsored-by: Klara, Inc. Sponsored-by: Wasabi Technology, Inc. Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Tony Hutter <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Rob Norris <[email protected]> Closes openzfs#16947
1 parent ceb04bf commit c1bc99e

File tree

7 files changed

+100
-15
lines changed

7 files changed

+100
-15
lines changed

cmd/zinject/zinject.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ static const char *const iotypestrtable[ZINJECT_IOTYPES] = {
251251
[ZINJECT_IOTYPE_FLUSH] = "flush",
252252
[ZINJECT_IOTYPE_TRIM] = "trim",
253253
[ZINJECT_IOTYPE_ALL] = "all",
254+
[ZINJECT_IOTYPE_PROBE] = "probe",
254255
};
255256

256257
static zinject_iotype_t

include/sys/zfs_ioctl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,8 @@ typedef enum zinject_iotype {
471471
ZINJECT_IOTYPE_TRIM = ZIO_TYPE_TRIM,
472472
ZINJECT_IOTYPE_ALL = ZIO_TYPES,
473473
/* Room for future expansion for ZIO_TYPE_* */
474-
ZINJECT_IOTYPES = 16,
474+
ZINJECT_IOTYPE_PROBE = 16,
475+
ZINJECT_IOTYPES,
475476
} zinject_iotype_t;
476477

477478
typedef struct zfs_share {

man/man8/zinject.8

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
.\" CDDL HEADER END
2020
.\"
2121
.\" Copyright 2013 Darik Horn <[email protected]>. All rights reserved.
22-
.\" Copyright (c) 2024, Klara Inc.
22+
.\" Copyright (c) 2024, 2025, Klara, Inc.
2323
.\"
2424
.\" lint-ok: WARNING: sections out of conventional order: Sh SYNOPSIS
2525
.\"
26-
.Dd December 2, 2024
26+
.Dd January 14, 2025
2727
.Dt ZINJECT 8
2828
.Os
2929
.
@@ -265,15 +265,16 @@ will be translated to the appropriate blkid range according to the
265265
object's properties.
266266
.It Fl s Ar seconds
267267
Run for this many seconds before reporting failure.
268-
.It Fl T Ar failure
269-
Set the failure type to one of
270-
.Sy all ,
271-
.Sy flush ,
272-
.Sy claim ,
273-
.Sy free ,
274-
.Sy read ,
275-
or
276-
.Sy write .
268+
.It Fl T Ar type
269+
Inject the error into I/O of this type.
270+
.Bl -tag -compact -width "read, write, flush, claim, free"
271+
.It Sy read , Sy write , Sy flush , Sy claim , Sy free
272+
Fundamental I/O types
273+
.It Sy all
274+
All fundamental I/O types
275+
.It Sy probe
276+
Device probe I/O
277+
.El
277278
.It Fl t Ar mos_type
278279
Set this to
279280
.Bl -tag -compact -width "spacemap"

module/zfs/zio_inject.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,10 @@ zio_match_iotype(zio_t *zio, uint32_t iotype)
386386
if (iotype >= ZINJECT_IOTYPES)
387387
return (B_FALSE);
388388

389+
/* Probe IOs only match IOTYPE_PROBE, regardless of their type. */
390+
if (zio->io_flags & ZIO_FLAG_PROBE)
391+
return (iotype == ZINJECT_IOTYPE_PROBE);
392+
389393
/* Standard IO types, match against ZIO type. */
390394
if (iotype < ZINJECT_IOTYPE_ALL)
391395
return (iotype == zio->io_type);
@@ -405,9 +409,11 @@ zio_handle_device_injection_impl(vdev_t *vd, zio_t *zio, int err1, int err2)
405409

406410
/*
407411
* We skip over faults in the labels unless it's during device open
408-
* (i.e. zio == NULL) or a device flush (offset is meaningless)
412+
* (i.e. zio == NULL) or a device flush (offset is meaningless). We let
413+
* probe IOs through so we can match them to probe inject records.
409414
*/
410-
if (zio != NULL && zio->io_type != ZIO_TYPE_FLUSH) {
415+
if (zio != NULL && zio->io_type != ZIO_TYPE_FLUSH &&
416+
!(zio->io_flags & ZIO_FLAG_PROBE)) {
411417
uint64_t offset = zio->io_offset;
412418

413419
if (offset < VDEV_LABEL_START_SIZE ||

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', 'zinject_counts']
162+
tests = ['zinject_args', 'zinject_counts', 'zinject_probe']
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
@@ -616,6 +616,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
616616
functional/cli_root/json/json_sanity.ksh \
617617
functional/cli_root/zinject/zinject_args.ksh \
618618
functional/cli_root/zinject/zinject_counts.ksh \
619+
functional/cli_root/zinject/zinject_probe.ksh \
619620
functional/cli_root/zdb/zdb_002_pos.ksh \
620621
functional/cli_root/zdb/zdb_003_pos.ksh \
621622
functional/cli_root/zdb/zdb_004_pos.ksh \
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/bin/ksh -p
2+
#
3+
# CDDL HEADER START
4+
#
5+
# The contents of this file are subject to the terms of the
6+
# Common Development and Distribution License (the "License").
7+
# You may not use this file except in compliance with the License.
8+
#
9+
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10+
# or https://opensource.org/licenses/CDDL-1.0.
11+
# See the License for the specific language governing permissions
12+
# and limitations under the License.
13+
#
14+
# When distributing Covered Code, include this CDDL HEADER in each
15+
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16+
# If applicable, add the following below this CDDL HEADER, with the
17+
# fields enclosed by brackets "[]" replaced with your own identifying
18+
# information: Portions Copyright [yyyy] [name of copyright owner]
19+
#
20+
# CDDL HEADER END
21+
#
22+
23+
#
24+
# Copyright (c) 2025, Klara, Inc.
25+
#
26+
27+
. $STF_SUITE/include/libtest.shlib
28+
29+
verify_runnable "global"
30+
31+
log_assert "Check zinject can correctly inject a probe failure."
32+
33+
DISK1=${DISKS%% *}
34+
35+
function cleanup
36+
{
37+
log_pos zinject -c all
38+
log_pos zpool clear $TESTPOOL
39+
log_pos zpool destroy -f $TESTPOOL
40+
log_pos restore_tunable TXG_TIMEOUT
41+
}
42+
43+
log_onexit cleanup
44+
45+
log_must zpool create $TESTPOOL $DISK1
46+
47+
# set the txg timeout a long way out, to try and avoid the pool syncing
48+
# between error injection and writing
49+
save_tunable TXG_TIMEOUT
50+
log_must set_tunable32 TXG_TIMEOUT 600
51+
52+
# force a sync now
53+
log_must zpool sync -f
54+
55+
# write stuff. this should go into memory, not written yet
56+
log_must dd if=/dev/urandom of=/$TESTPOOL/file bs=1M count=1
57+
58+
# inject faults
59+
log_must zinject -d $DISK1 -e io -T probe $TESTPOOL
60+
log_must zinject -d $DISK1 -e io -T write $TESTPOOL
61+
62+
# force the sync now. backgrounded, because the pool will suspend and we don't
63+
# want to block.
64+
log_pos zpool sync &
65+
66+
log_note "waiting for pool to suspend"
67+
typeset -i tries=30
68+
until [[ $(kstat_pool $TESTPOOL state) == "SUSPENDED" ]] ; do
69+
if ((tries-- == 0)); then
70+
log_fail "pool didn't suspend"
71+
fi
72+
sleep 1
73+
done
74+
75+
log_pass "zinject can correctly inject a probe failure."

0 commit comments

Comments
 (0)