xref: /illumos-gate/usr/src/cmd/zinject/zinject.c (revision 3382f241)
1ea8dc4b6Seschrock /*
2ea8dc4b6Seschrock  * CDDL HEADER START
3ea8dc4b6Seschrock  *
4ea8dc4b6Seschrock  * The contents of this file are subject to the terms of the
5ea8dc4b6Seschrock  * Common Development and Distribution License (the "License").
6ea8dc4b6Seschrock  * You may not use this file except in compliance with the License.
7ea8dc4b6Seschrock  *
8ea8dc4b6Seschrock  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9ea8dc4b6Seschrock  * or http://www.opensolaris.org/os/licensing.
10ea8dc4b6Seschrock  * See the License for the specific language governing permissions
11ea8dc4b6Seschrock  * and limitations under the License.
12ea8dc4b6Seschrock  *
13ea8dc4b6Seschrock  * When distributing Covered Code, include this CDDL HEADER in each
14ea8dc4b6Seschrock  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15ea8dc4b6Seschrock  * If applicable, add the following below this CDDL HEADER, with the
16ea8dc4b6Seschrock  * fields enclosed by brackets "[]" replaced with your own identifying
17ea8dc4b6Seschrock  * information: Portions Copyright [yyyy] [name of copyright owner]
18ea8dc4b6Seschrock  *
19ea8dc4b6Seschrock  * CDDL HEADER END
20ea8dc4b6Seschrock  */
21ea8dc4b6Seschrock /*
2298d1cbfeSGeorge Wilson  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
2397e81309SPrakash Surya  * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
24b853d39aSDon Brady  * Copyright (c) 2017, Intel Corporation.
25ea8dc4b6Seschrock  */
26ea8dc4b6Seschrock 
27ea8dc4b6Seschrock /*
28ea8dc4b6Seschrock  * ZFS Fault Injector
29ea8dc4b6Seschrock  *
30ea8dc4b6Seschrock  * This userland component takes a set of options and uses libzpool to translate
31ea8dc4b6Seschrock  * from a user-visible object type and name to an internal representation.
32ea8dc4b6Seschrock  * There are two basic types of faults: device faults and data faults.
33ea8dc4b6Seschrock  *
34ea8dc4b6Seschrock  *
35ea8dc4b6Seschrock  * DEVICE FAULTS
36ea8dc4b6Seschrock  *
37ea8dc4b6Seschrock  * Errors can be injected into a particular vdev using the '-d' option.  This
38ea8dc4b6Seschrock  * option takes a path or vdev GUID to uniquely identify the device within a
39ea8dc4b6Seschrock  * pool.  There are two types of errors that can be injected, EIO and ENXIO,
4021bf64a7Sgw  * that can be controlled through the '-e' option.  The default is ENXIO.  For
41ea8dc4b6Seschrock  * EIO failures, any attempt to read data from the device will return EIO, but
42ea8dc4b6Seschrock  * subsequent attempt to reopen the device will succeed.  For ENXIO failures,
43ea8dc4b6Seschrock  * any attempt to read from the device will return EIO, but any attempt to
44ea8dc4b6Seschrock  * reopen the device will also return ENXIO.
4521bf64a7Sgw  * For label faults, the -L option must be specified. This allows faults
4698d1cbfeSGeorge Wilson  * to be injected into either the nvlist, uberblock, pad1, or pad2 region
4798d1cbfeSGeorge Wilson  * of all the labels for the specified device.
48ea8dc4b6Seschrock  *
49ea8dc4b6Seschrock  * This form of the command looks like:
50ea8dc4b6Seschrock  *
5112a8814cSTom Caputi  *	zinject -d device [-e errno] [-L <uber | nvlist | pad1 | pad2>] pool
52ea8dc4b6Seschrock  *
53ea8dc4b6Seschrock  *
54ea8dc4b6Seschrock  * DATA FAULTS
55ea8dc4b6Seschrock  *
56ea8dc4b6Seschrock  * We begin with a tuple of the form:
57ea8dc4b6Seschrock  *
5812a8814cSTom Caputi  *	<type,level,range,object>
59ea8dc4b6Seschrock  *
6012a8814cSTom Caputi  *	type	A string describing the type of data to target.  Each type
6112a8814cSTom Caputi  *		implicitly describes how to interpret 'object'. Currently,
6212a8814cSTom Caputi  *		the following values are supported:
63ea8dc4b6Seschrock  *
6412a8814cSTom Caputi  *		data		User data for a file
6512a8814cSTom Caputi  *		dnode		Dnode for a file or directory
66ea8dc4b6Seschrock  *
67ea8dc4b6Seschrock  *		The following MOS objects are special.  Instead of injecting
68ea8dc4b6Seschrock  *		errors on a particular object or blkid, we inject errors across
69ea8dc4b6Seschrock  *		all objects of the given type.
70ea8dc4b6Seschrock  *
7112a8814cSTom Caputi  *		mos		Any data in the MOS
7212a8814cSTom Caputi  *		mosdir		object directory
7312a8814cSTom Caputi  *		config		pool configuration
7412a8814cSTom Caputi  *		bpobj		blkptr list
7512a8814cSTom Caputi  *		spacemap	spacemap
7612a8814cSTom Caputi  *		metaslab	metaslab
7712a8814cSTom Caputi  *		errlog		persistent error log
78ea8dc4b6Seschrock  *
7912a8814cSTom Caputi  *	level	Object level.  Defaults to '0', not applicable to all types.  If
8012a8814cSTom Caputi  *		a range is given, this corresponds to the indirect block
8112a8814cSTom Caputi  *		corresponding to the specific range.
82ea8dc4b6Seschrock  *
83ea8dc4b6Seschrock  *	range	A numerical range [start,end) within the object.  Defaults to
84ea8dc4b6Seschrock  *		the full size of the file.
85ea8dc4b6Seschrock  *
8612a8814cSTom Caputi  *	object	A string describing the logical location of the object.  For
8712a8814cSTom Caputi  *		files and directories (currently the only supported types),
8812a8814cSTom Caputi  *		this is the path of the object on disk.
89ea8dc4b6Seschrock  *
90ea8dc4b6Seschrock  * This is translated, via libzpool, into the following internal representation:
91ea8dc4b6Seschrock  *
9212a8814cSTom Caputi  *	<type,objset,object,level,range>
93ea8dc4b6Seschrock  *
94ea8dc4b6Seschrock  * These types should be self-explanatory.  This tuple is then passed to the
95ea8dc4b6Seschrock  * kernel via a special ioctl() to initiate fault injection for the given
96ea8dc4b6Seschrock  * object.  Note that 'type' is not strictly necessary for fault injection, but
97ea8dc4b6Seschrock  * is used when translating existing faults into a human-readable string.
98ea8dc4b6Seschrock  *
99ea8dc4b6Seschrock  *
100ea8dc4b6Seschrock  * The command itself takes one of the forms:
101ea8dc4b6Seschrock  *
10212a8814cSTom Caputi  *	zinject
10312a8814cSTom Caputi  *	zinject <-a | -u pool>
10412a8814cSTom Caputi  *	zinject -c <id|all>
10512a8814cSTom Caputi  *	zinject [-q] <-t type> [-f freq] [-u] [-a] [-m] [-e errno] [-l level]
106ea8dc4b6Seschrock  *	    [-r range] <object>
10712a8814cSTom Caputi  *	zinject [-f freq] [-a] [-m] [-u] -b objset:object:level:start:end pool
108ea8dc4b6Seschrock  *
109ea8dc4b6Seschrock  * With no arguments, the command prints all currently registered injection
110ea8dc4b6Seschrock  * handlers, with their numeric identifiers.
111ea8dc4b6Seschrock  *
112ea8dc4b6Seschrock  * The '-c' option will clear the given handler, or all handlers if 'all' is
113ea8dc4b6Seschrock  * specified.
114ea8dc4b6Seschrock  *
115ea8dc4b6Seschrock  * The '-e' option takes a string describing the errno to simulate.  This must
116eb633035STom Caputi  * be one of 'io', 'checksum', or 'decrypt'.  In most cases this will result
117eb633035STom Caputi  * in the same behavior, but RAID-Z will produce a different set of ereports
118eb633035STom Caputi  * for this situation.
119ea8dc4b6Seschrock  *
120ea8dc4b6Seschrock  * The '-a', '-u', and '-m' flags toggle internal flush behavior.  If '-a' is
121ea8dc4b6Seschrock  * specified, then the ARC cache is flushed appropriately.  If '-u' is
122ea8dc4b6Seschrock  * specified, then the underlying SPA is unloaded.  Either of these flags can be
123ea8dc4b6Seschrock  * specified independently of any other handlers.  The '-m' flag automatically
124ea8dc4b6Seschrock  * does an unmount and remount of the underlying dataset to aid in flushing the
125ea8dc4b6Seschrock  * cache.
126ea8dc4b6Seschrock  *
127ea8dc4b6Seschrock  * The '-f' flag controls the frequency of errors injected, expressed as a
128b853d39aSDon Brady  * real number percentage between 0.0001 and 100.  The default is 100.
129ea8dc4b6Seschrock  *
130ea8dc4b6Seschrock  * The this form is responsible for actually injecting the handler into the
131ea8dc4b6Seschrock  * framework.  It takes the arguments described above, translates them to the
132ea8dc4b6Seschrock  * internal tuple using libzpool, and then issues an ioctl() to register the
133ea8dc4b6Seschrock  * handler.
134ea8dc4b6Seschrock  *
135ea8dc4b6Seschrock  * The final form can target a specific bookmark, regardless of whether a
136ea8dc4b6Seschrock  * human-readable interface has been designed.  It allows developers to specify
137ea8dc4b6Seschrock  * a particular block by number.
138ea8dc4b6Seschrock  */
139ea8dc4b6Seschrock 
140ea8dc4b6Seschrock #include <errno.h>
141ea8dc4b6Seschrock #include <fcntl.h>
142ea8dc4b6Seschrock #include <stdio.h>
143ea8dc4b6Seschrock #include <stdlib.h>
144ea8dc4b6Seschrock #include <strings.h>
145ea8dc4b6Seschrock #include <unistd.h>
146ea8dc4b6Seschrock 
147ea8dc4b6Seschrock #include <sys/fs/zfs.h>
148ea8dc4b6Seschrock #include <sys/mount.h>
149ea8dc4b6Seschrock 
150ea8dc4b6Seschrock #include <libzfs.h>
151ea8dc4b6Seschrock 
152ea8dc4b6Seschrock #undef verify	/* both libzfs.h and zfs_context.h want to define this */
153ea8dc4b6Seschrock 
154ea8dc4b6Seschrock #include "zinject.h"
155ea8dc4b6Seschrock 
15699653d4eSeschrock libzfs_handle_t *g_zfs;
157ea8dc4b6Seschrock int zfs_fd;
158ea8dc4b6Seschrock 
159ea8dc4b6Seschrock #define	ECKSUM	EBADE
160ea8dc4b6Seschrock 
161ea8dc4b6Seschrock static const char *errtable[TYPE_INVAL] = {
162ea8dc4b6Seschrock 	"data",
163ea8dc4b6Seschrock 	"dnode",
164ea8dc4b6Seschrock 	"mos",
165ea8dc4b6Seschrock 	"mosdir",
166ea8dc4b6Seschrock 	"metaslab",
167ea8dc4b6Seschrock 	"config",
168cde58dbcSMatthew Ahrens 	"bpobj",
169ea8dc4b6Seschrock 	"spacemap",
17021bf64a7Sgw 	"errlog",
17121bf64a7Sgw 	"uber",
17298d1cbfeSGeorge Wilson 	"nvlist",
17398d1cbfeSGeorge Wilson 	"pad1",
17498d1cbfeSGeorge Wilson 	"pad2"
175ea8dc4b6Seschrock };
176ea8dc4b6Seschrock 
177ea8dc4b6Seschrock static err_type_t
name_to_type(const char * arg)178ea8dc4b6Seschrock name_to_type(const char *arg)
179ea8dc4b6Seschrock {
180ea8dc4b6Seschrock 	int i;
181ea8dc4b6Seschrock 	for (i = 0; i < TYPE_INVAL; i++)
182ea8dc4b6Seschrock 		if (strcmp(errtable[i], arg) == 0)
183ea8dc4b6Seschrock 			return (i);
184ea8dc4b6Seschrock 
185ea8dc4b6Seschrock 	return (TYPE_INVAL);
186ea8dc4b6Seschrock }
187ea8dc4b6Seschrock 
188ea8dc4b6Seschrock static const char *
type_to_name(uint64_t type)189ea8dc4b6Seschrock type_to_name(uint64_t type)
190ea8dc4b6Seschrock {
191ea8dc4b6Seschrock 	switch (type) {
192ea8dc4b6Seschrock 	case DMU_OT_OBJECT_DIRECTORY:
193ea8dc4b6Seschrock 		return ("mosdir");
194ea8dc4b6Seschrock 	case DMU_OT_OBJECT_ARRAY:
195ea8dc4b6Seschrock 		return ("metaslab");
196ea8dc4b6Seschrock 	case DMU_OT_PACKED_NVLIST:
197ea8dc4b6Seschrock 		return ("config");
198cde58dbcSMatthew Ahrens 	case DMU_OT_BPOBJ:
199cde58dbcSMatthew Ahrens 		return ("bpobj");
200ea8dc4b6Seschrock 	case DMU_OT_SPACE_MAP:
201ea8dc4b6Seschrock 		return ("spacemap");
202ea8dc4b6Seschrock 	case DMU_OT_ERROR_LOG:
203ea8dc4b6Seschrock 		return ("errlog");
204ea8dc4b6Seschrock 	default:
205ea8dc4b6Seschrock 		return ("-");
206ea8dc4b6Seschrock 	}
207ea8dc4b6Seschrock }
208ea8dc4b6Seschrock 
209ea8dc4b6Seschrock 
210ea8dc4b6Seschrock /*
211ea8dc4b6Seschrock  * Print usage message.
212