Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 Mar 2016 00:13:39 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r297108 - in stable/10: cddl/contrib/opensolaris/cmd/zinject cddl/contrib/opensolaris/lib/libzfs/common sys/cddl/compat/opensolaris/sys sys/cddl/contrib/opensolaris/common/zfs sys/cddl/...
Message-ID:  <201603210013.u2L0DdJl034841@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Mon Mar 21 00:13:39 2016
New Revision: 297108
URL: https://svnweb.freebsd.org/changeset/base/297108

Log:
  MFC r296510, r296563, r296567: MFV r296505:
  6531 Provide mechanism to artificially limit disk performance
  
  Reviewed by: Paul Dagnelie <pcd@delphix.com>
  Reviewed by: Matthew Ahrens <mahrens@delphix.com>
  Reviewed by: George Wilson <george.wilson@delphix.com>
  Approved by: Dan McDonald <danmcd@omniti.com>
  Author: Prakash Surya <prakash.surya@delphix.com>
  
  illumos/illumos-gate@97e81309571898df9fdd94aab1216dfcf23e060b

Added:
  stable/10/sys/cddl/compat/opensolaris/sys/callo.h
     - copied unchanged from r296510, head/sys/cddl/compat/opensolaris/sys/callo.h
Modified:
  stable/10/cddl/contrib/opensolaris/cmd/zinject/zinject.c
  stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c
  stable/10/sys/cddl/compat/opensolaris/sys/systm.h
  stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
  stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_context.h
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_disk.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_file.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
  stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_inject.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/cddl/contrib/opensolaris/cmd/zinject/zinject.c
==============================================================================
--- stable/10/cddl/contrib/opensolaris/cmd/zinject/zinject.c	Mon Mar 21 00:09:56 2016	(r297107)
+++ stable/10/cddl/contrib/opensolaris/cmd/zinject/zinject.c	Mon Mar 21 00:13:39 2016	(r297108)
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
  */
 
 /*
@@ -229,21 +229,57 @@ usage(void)
 	    "\t\tall records if 'all' is specificed.\n"
 	    "\n"
 	    "\tzinject -p <function name> pool\n"
+	    "\n"
 	    "\t\tInject a panic fault at the specified function. Only \n"
 	    "\t\tfunctions which call spa_vdev_config_exit(), or \n"
 	    "\t\tspa_vdev_exit() will trigger a panic.\n"
 	    "\n"
 	    "\tzinject -d device [-e errno] [-L <nvlist|uber|pad1|pad2>] [-F]\n"
 	    "\t    [-T <read|write|free|claim|all> pool\n"
+	    "\n"
 	    "\t\tInject a fault into a particular device or the device's\n"
 	    "\t\tlabel.  Label injection can either be 'nvlist', 'uber',\n "
 	    "\t\t'pad1', or 'pad2'.\n"
 	    "\t\t'errno' can be 'nxio' (the default), 'io', or 'dtl'.\n"
 	    "\n"
 	    "\tzinject -d device -A <degrade|fault> pool\n"
+	    "\n"
 	    "\t\tPerform a specific action on a particular device\n"
 	    "\n"
+	    "\tzinject -d device -D latency:lanes pool\n"
+	    "\n"
+	    "\t\tAdd an artificial delay to IO requests on a particular\n"
+	    "\t\tdevice, such that the requests take a minimum of 'latency'\n"
+	    "\t\tmilliseconds to complete. Each delay has an associated\n"
+	    "\t\tnumber of 'lanes' which defines the number of concurrent\n"
+	    "\t\tIO requests that can be processed.\n"
+	    "\n"
+	    "\t\tFor example, with a single lane delay of 10 ms (-D 10:1),\n"
+	    "\t\tthe device will only be able to service a single IO request\n"
+	    "\t\tat a time with each request taking 10 ms to complete. So,\n"
+	    "\t\tif only a single request is submitted every 10 ms, the\n"
+	    "\t\taverage latency will be 10 ms; but if more than one request\n"
+	    "\t\tis submitted every 10 ms, the average latency will be more\n"
+	    "\t\tthan 10 ms.\n"
+	    "\n"
+	    "\t\tSimilarly, if a delay of 10 ms is specified to have two\n"
+	    "\t\tlanes (-D 10:2), then the device will be able to service\n"
+	    "\t\ttwo requests at a time, each with a minimum latency of\n"
+	    "\t\t10 ms. So, if two requests are submitted every 10 ms, then\n"
+	    "\t\tthe average latency will be 10 ms; but if more than two\n"
+	    "\t\trequests are submitted every 10 ms, the average latency\n"
+	    "\t\twill be more than 10 ms.\n"
+	    "\n"
+	    "\t\tAlso note, these delays are additive. So two invocations\n"
+	    "\t\tof '-D 10:1', is roughly equivalent to a single invocation\n"
+	    "\t\tof '-D 10:2'. This also means, one can specify multiple\n"
+	    "\t\tlanes with differing target latencies. For example, an\n"
+	    "\t\tinvocation of '-D 10:1' followed by '-D 25:2' will\n"
+	    "\t\tcreate 3 lanes on the device; one lane with a latency\n"
+	    "\t\tof 10 ms and two lanes with a 25 ms latency.\n"
+	    "\n"
 	    "\tzinject -I [-s <seconds> | -g <txgs>] pool\n"
+	    "\n"
 	    "\t\tCause the pool to stop writing blocks yet not\n"
 	    "\t\treport errors for a duration.  Simulates buggy hardware\n"
 	    "\t\tthat fails to honor cache flush requests.\n"
@@ -357,6 +393,9 @@ print_device_handler(int id, const char 
 	if (record->zi_guid == 0 || record->zi_func[0] != '\0')
 		return (0);
 
+	if (record->zi_cmd == ZINJECT_DELAY_IO)
+		return (0);
+
 	if (*count == 0) {
 		(void) printf("%3s  %-15s  %s\n", "ID", "POOL", "GUID");
 		(void) printf("---  ---------------  ----------------\n");
@@ -371,6 +410,35 @@ print_device_handler(int id, const char 
 }
 
 static int
+print_delay_handler(int id, const char *pool, zinject_record_t *record,
+    void *data)
+{
+	int *count = data;
+
+	if (record->zi_guid == 0 || record->zi_func[0] != '\0')
+		return (0);
+
+	if (record->zi_cmd != ZINJECT_DELAY_IO)
+		return (0);
+
+	if (*count == 0) {
+		(void) printf("%3s  %-15s  %-15s  %-15s  %s\n",
+		    "ID", "POOL", "DELAY (ms)", "LANES", "GUID");
+		(void) printf("---  ---------------  ---------------  "
+		    "---------------  ----------------\n");
+	}
+
+	*count += 1;
+
+	(void) printf("%3d  %-15s  %-15llu  %-15llu  %llx\n", id, pool,
+	    (u_longlong_t)NSEC2MSEC(record->zi_timer),
+	    (u_longlong_t)record->zi_nlanes,
+	    (u_longlong_t)record->zi_guid);
+
+	return (0);
+}
+
+static int
 print_panic_handler(int id, const char *pool, zinject_record_t *record,
     void *data)
 {
@@ -407,6 +475,13 @@ print_all_handlers(void)
 		count = 0;
 	}
 
+	(void) iter_handlers(print_delay_handler, &count);
+	if (count > 0) {
+		total += count;
+		(void) printf("\n");
+		count = 0;
+	}
+
 	(void) iter_handlers(print_data_handler, &count);
 	if (count > 0) {
 		total += count;
@@ -549,6 +624,35 @@ perform_action(const char *pool, zinject
 	return (1);
 }
 
+static int
+parse_delay(char *str, uint64_t *delay, uint64_t *nlanes)
+{
+	unsigned long scan_delay;
+	unsigned long scan_nlanes;
+
+	if (sscanf(str, "%lu:%lu", &scan_delay, &scan_nlanes) != 2)
+		return (1);
+
+	/*
+	 * We explicitly disallow a delay of zero here, because we key
+	 * off this value being non-zero in translate_device(), to
+	 * determine if the fault is a ZINJECT_DELAY_IO fault or not.
+	 */
+	if (scan_delay == 0)
+		return (1);
+
+	/*
+	 * The units for the CLI delay parameter is milliseconds, but
+	 * the data passed to the kernel is interpreted as nanoseconds.
+	 * Thus we scale the milliseconds to nanoseconds here, and this
+	 * nanosecond value is used to pass the delay to the kernel.
+	 */
+	*delay = MSEC2NSEC(scan_delay);
+	*nlanes = scan_nlanes;
+
+	return (0);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -632,8 +736,9 @@ main(int argc, char **argv)
 			device = optarg;
 			break;
 		case 'D':
-			record.zi_timer = strtoull(optarg, &end, 10);
-			if (errno != 0 || *end != '\0') {
+			ret = parse_delay(optarg, &record.zi_timer,
+			    &record.zi_nlanes);
+			if (ret != 0) {
 				(void) fprintf(stderr, "invalid i/o delay "
 				    "value: '%s'\n", optarg);
 				usage();

Modified: stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c
==============================================================================
--- stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c	Mon Mar 21 00:09:56 2016	(r297107)
+++ stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c	Mon Mar 21 00:13:39 2016	(r297108)
@@ -74,6 +74,9 @@ zcmd_ioctl(int fd, int request, zfs_cmd_
 
 	if (zfs_ioctl_version >= ZFS_IOCVER_DEADMAN) {
 		switch (zfs_ioctl_version) {
+		case ZFS_IOCVER_RESUME:
+			cflag = ZFS_CMD_COMPAT_RESUME;
+			break;
 		case ZFS_IOCVER_EDBP:
 			cflag = ZFS_CMD_COMPAT_EDBP;
 			break;

Copied: stable/10/sys/cddl/compat/opensolaris/sys/callo.h (from r296510, head/sys/cddl/compat/opensolaris/sys/callo.h)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/10/sys/cddl/compat/opensolaris/sys/callo.h	Mon Mar 21 00:13:39 2016	(r297108, copy of r296510, head/sys/cddl/compat/opensolaris/sys/callo.h)
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2016 Alexander Motin <mav@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _OPENSOLARIS_SYS_CALLO_H_
+#define	_OPENSOLARIS_SYS_CALLO_H_
+
+#include_next <sys/callout.h>
+
+#define	CALLOUT_REALTIME	0		/* realtime callout type */
+#define	CALLOUT_NORMAL		1		/* normal callout type */
+
+#endif	/* !_OPENSOLARIS_SYS_CALLO_H_ */

Modified: stable/10/sys/cddl/compat/opensolaris/sys/systm.h
==============================================================================
--- stable/10/sys/cddl/compat/opensolaris/sys/systm.h	Mon Mar 21 00:09:56 2016	(r297107)
+++ stable/10/sys/cddl/compat/opensolaris/sys/systm.h	Mon Mar 21 00:13:39 2016	(r297108)
@@ -42,6 +42,9 @@
 
 #define	delay(x)	pause("soldelay", (x))
 
+#define	timeout_generic(type, fn, arg, t, r, f)			\
+    timeout(fn, arg, t / (NANOSEC/hz) + 1)
+
 #endif	/* _KERNEL */
 
 #endif	/* _OPENSOLARIS_SYS_SYSTM_H_ */

Modified: stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c	Mon Mar 21 00:09:56 2016	(r297107)
+++ stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c	Mon Mar 21 00:13:39 2016	(r297108)
@@ -54,8 +54,69 @@ zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_
 	zfs_cmd_deadman_t *zcdm_c;
 	zfs_cmd_zcmd_t *zcmd_c;
 	zfs_cmd_edbp_t *edbp_c;
+	zfs_cmd_resume_t *resume_c;
 
 	switch (cflag) {
+	case ZFS_CMD_COMPAT_RESUME:
+		resume_c = (void *)addr;
+		/* zc */
+		strlcpy(zc->zc_name, resume_c->zc_name, MAXPATHLEN);
+		strlcpy(zc->zc_value, resume_c->zc_value, MAXPATHLEN * 2);
+		strlcpy(zc->zc_string, resume_c->zc_string, MAXPATHLEN);
+
+#define FIELD_COPY(field) zc->field = resume_c->field
+		FIELD_COPY(zc_nvlist_src);
+		FIELD_COPY(zc_nvlist_src_size);
+		FIELD_COPY(zc_nvlist_dst);
+		FIELD_COPY(zc_nvlist_dst_size);
+		FIELD_COPY(zc_nvlist_dst_filled);
+		FIELD_COPY(zc_pad2);
+		FIELD_COPY(zc_history);
+		FIELD_COPY(zc_guid);
+		FIELD_COPY(zc_nvlist_conf);
+		FIELD_COPY(zc_nvlist_conf_size);
+		FIELD_COPY(zc_cookie);
+		FIELD_COPY(zc_objset_type);
+		FIELD_COPY(zc_perm_action);
+		FIELD_COPY(zc_history_len);
+		FIELD_COPY(zc_history_offset);
+		FIELD_COPY(zc_obj);
+		FIELD_COPY(zc_iflags);
+		FIELD_COPY(zc_share);
+		FIELD_COPY(zc_jailid);
+		FIELD_COPY(zc_objset_stats);
+		FIELD_COPY(zc_begin_record);
+		FIELD_COPY(zc_inject_record.zi_objset);
+		FIELD_COPY(zc_inject_record.zi_object);
+		FIELD_COPY(zc_inject_record.zi_start);
+		FIELD_COPY(zc_inject_record.zi_end);
+		FIELD_COPY(zc_inject_record.zi_guid);
+		FIELD_COPY(zc_inject_record.zi_level);
+		FIELD_COPY(zc_inject_record.zi_error);
+		FIELD_COPY(zc_inject_record.zi_type);
+		FIELD_COPY(zc_inject_record.zi_freq);
+		FIELD_COPY(zc_inject_record.zi_failfast);
+		strlcpy(zc->zc_inject_record.zi_func,
+		    resume_c->zc_inject_record.zi_func, MAXNAMELEN);
+		FIELD_COPY(zc_inject_record.zi_iotype);
+		FIELD_COPY(zc_inject_record.zi_duration);
+		FIELD_COPY(zc_inject_record.zi_timer);
+		zc->zc_inject_record.zi_nlanes = 1;
+		FIELD_COPY(zc_inject_record.zi_cmd);
+		FIELD_COPY(zc_inject_record.zi_pad);
+		FIELD_COPY(zc_defer_destroy);
+		FIELD_COPY(zc_flags);
+		FIELD_COPY(zc_action_handle);
+		FIELD_COPY(zc_cleanup_fd);
+		FIELD_COPY(zc_simple);
+		FIELD_COPY(zc_resumable);
+		FIELD_COPY(zc_sendobj);
+		FIELD_COPY(zc_fromobj);
+		FIELD_COPY(zc_createtxg);
+		FIELD_COPY(zc_stat);
+#undef FIELD_COPY
+		break;
+
 	case ZFS_CMD_COMPAT_EDBP:
 		edbp_c = (void *)addr;
 		/* zc */
@@ -63,40 +124,57 @@ zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_
 		strlcpy(zc->zc_value, edbp_c->zc_value, MAXPATHLEN * 2);
 		strlcpy(zc->zc_string, edbp_c->zc_string, MAXPATHLEN);
 
-#define ZCMD_COPY(field) zc->field = edbp_c->field
-		ZCMD_COPY(zc_nvlist_src);
-		ZCMD_COPY(zc_nvlist_src_size);
-		ZCMD_COPY(zc_nvlist_dst);
-		ZCMD_COPY(zc_nvlist_dst_size);
-		ZCMD_COPY(zc_nvlist_dst_filled);
-		ZCMD_COPY(zc_pad2);
-		ZCMD_COPY(zc_history);
-		ZCMD_COPY(zc_guid);
-		ZCMD_COPY(zc_nvlist_conf);
-		ZCMD_COPY(zc_nvlist_conf_size);
-		ZCMD_COPY(zc_cookie);
-		ZCMD_COPY(zc_objset_type);
-		ZCMD_COPY(zc_perm_action);
-		ZCMD_COPY(zc_history_len);
-		ZCMD_COPY(zc_history_offset);
-		ZCMD_COPY(zc_obj);
-		ZCMD_COPY(zc_iflags);
-		ZCMD_COPY(zc_share);
-		ZCMD_COPY(zc_jailid);
-		ZCMD_COPY(zc_objset_stats);
+#define FIELD_COPY(field) zc->field = edbp_c->field
+		FIELD_COPY(zc_nvlist_src);
+		FIELD_COPY(zc_nvlist_src_size);
+		FIELD_COPY(zc_nvlist_dst);
+		FIELD_COPY(zc_nvlist_dst_size);
+		FIELD_COPY(zc_nvlist_dst_filled);
+		FIELD_COPY(zc_pad2);
+		FIELD_COPY(zc_history);
+		FIELD_COPY(zc_guid);
+		FIELD_COPY(zc_nvlist_conf);
+		FIELD_COPY(zc_nvlist_conf_size);
+		FIELD_COPY(zc_cookie);
+		FIELD_COPY(zc_objset_type);
+		FIELD_COPY(zc_perm_action);
+		FIELD_COPY(zc_history_len);
+		FIELD_COPY(zc_history_offset);
+		FIELD_COPY(zc_obj);
+		FIELD_COPY(zc_iflags);
+		FIELD_COPY(zc_share);
+		FIELD_COPY(zc_jailid);
+		FIELD_COPY(zc_objset_stats);
 		zc->zc_begin_record.drr_u.drr_begin = edbp_c->zc_begin_record;
-		ZCMD_COPY(zc_inject_record);
-		ZCMD_COPY(zc_defer_destroy);
-		ZCMD_COPY(zc_flags);
-		ZCMD_COPY(zc_action_handle);
-		ZCMD_COPY(zc_cleanup_fd);
-		ZCMD_COPY(zc_simple);
+		FIELD_COPY(zc_inject_record.zi_objset);
+		FIELD_COPY(zc_inject_record.zi_object);
+		FIELD_COPY(zc_inject_record.zi_start);
+		FIELD_COPY(zc_inject_record.zi_end);
+		FIELD_COPY(zc_inject_record.zi_guid);
+		FIELD_COPY(zc_inject_record.zi_level);
+		FIELD_COPY(zc_inject_record.zi_error);
+		FIELD_COPY(zc_inject_record.zi_type);
+		FIELD_COPY(zc_inject_record.zi_freq);
+		FIELD_COPY(zc_inject_record.zi_failfast);
+		strlcpy(zc->zc_inject_record.zi_func,
+		    edbp_c->zc_inject_record.zi_func, MAXNAMELEN);
+		FIELD_COPY(zc_inject_record.zi_iotype);
+		FIELD_COPY(zc_inject_record.zi_duration);
+		FIELD_COPY(zc_inject_record.zi_timer);
+		zc->zc_inject_record.zi_nlanes = 1;
+		FIELD_COPY(zc_inject_record.zi_cmd);
+		FIELD_COPY(zc_inject_record.zi_pad);
+		FIELD_COPY(zc_defer_destroy);
+		FIELD_COPY(zc_flags);
+		FIELD_COPY(zc_action_handle);
+		FIELD_COPY(zc_cleanup_fd);
+		FIELD_COPY(zc_simple);
 		zc->zc_resumable = B_FALSE;
-		ZCMD_COPY(zc_sendobj);
-		ZCMD_COPY(zc_fromobj);
-		ZCMD_COPY(zc_createtxg);
-		ZCMD_COPY(zc_stat);
-#undef ZCMD_COPY
+		FIELD_COPY(zc_sendobj);
+		FIELD_COPY(zc_fromobj);
+		FIELD_COPY(zc_createtxg);
+		FIELD_COPY(zc_stat);
+#undef FIELD_COPY
 		break;
 
 	case ZFS_CMD_COMPAT_ZCMD:
@@ -106,43 +184,60 @@ zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_
 		strlcpy(zc->zc_value, zcmd_c->zc_value, MAXPATHLEN * 2);
 		strlcpy(zc->zc_string, zcmd_c->zc_string, MAXPATHLEN);
 
-#define ZCMD_COPY(field) zc->field = zcmd_c->field
-		ZCMD_COPY(zc_nvlist_src);
-		ZCMD_COPY(zc_nvlist_src_size);
-		ZCMD_COPY(zc_nvlist_dst);
-		ZCMD_COPY(zc_nvlist_dst_size);
-		ZCMD_COPY(zc_nvlist_dst_filled);
-		ZCMD_COPY(zc_pad2);
-		ZCMD_COPY(zc_history);
-		ZCMD_COPY(zc_guid);
-		ZCMD_COPY(zc_nvlist_conf);
-		ZCMD_COPY(zc_nvlist_conf_size);
-		ZCMD_COPY(zc_cookie);
-		ZCMD_COPY(zc_objset_type);
-		ZCMD_COPY(zc_perm_action);
-		ZCMD_COPY(zc_history_len);
-		ZCMD_COPY(zc_history_offset);
-		ZCMD_COPY(zc_obj);
-		ZCMD_COPY(zc_iflags);
-		ZCMD_COPY(zc_share);
-		ZCMD_COPY(zc_jailid);
-		ZCMD_COPY(zc_objset_stats);
+#define FIELD_COPY(field) zc->field = zcmd_c->field
+		FIELD_COPY(zc_nvlist_src);
+		FIELD_COPY(zc_nvlist_src_size);
+		FIELD_COPY(zc_nvlist_dst);
+		FIELD_COPY(zc_nvlist_dst_size);
+		FIELD_COPY(zc_nvlist_dst_filled);
+		FIELD_COPY(zc_pad2);
+		FIELD_COPY(zc_history);
+		FIELD_COPY(zc_guid);
+		FIELD_COPY(zc_nvlist_conf);
+		FIELD_COPY(zc_nvlist_conf_size);
+		FIELD_COPY(zc_cookie);
+		FIELD_COPY(zc_objset_type);
+		FIELD_COPY(zc_perm_action);
+		FIELD_COPY(zc_history_len);
+		FIELD_COPY(zc_history_offset);
+		FIELD_COPY(zc_obj);
+		FIELD_COPY(zc_iflags);
+		FIELD_COPY(zc_share);
+		FIELD_COPY(zc_jailid);
+		FIELD_COPY(zc_objset_stats);
 		zc->zc_begin_record.drr_u.drr_begin = zcmd_c->zc_begin_record;
-		ZCMD_COPY(zc_inject_record);
+		FIELD_COPY(zc_inject_record.zi_objset);
+		FIELD_COPY(zc_inject_record.zi_object);
+		FIELD_COPY(zc_inject_record.zi_start);
+		FIELD_COPY(zc_inject_record.zi_end);
+		FIELD_COPY(zc_inject_record.zi_guid);
+		FIELD_COPY(zc_inject_record.zi_level);
+		FIELD_COPY(zc_inject_record.zi_error);
+		FIELD_COPY(zc_inject_record.zi_type);
+		FIELD_COPY(zc_inject_record.zi_freq);
+		FIELD_COPY(zc_inject_record.zi_failfast);
+		strlcpy(zc->zc_inject_record.zi_func,
+		    zcmd_c->zc_inject_record.zi_func, MAXNAMELEN);
+		FIELD_COPY(zc_inject_record.zi_iotype);
+		FIELD_COPY(zc_inject_record.zi_duration);
+		FIELD_COPY(zc_inject_record.zi_timer);
+		zc->zc_inject_record.zi_nlanes = 1;
+		FIELD_COPY(zc_inject_record.zi_cmd);
+		FIELD_COPY(zc_inject_record.zi_pad);
 
 		/* boolean_t -> uint32_t */
 		zc->zc_defer_destroy = (uint32_t)(zcmd_c->zc_defer_destroy);
 		zc->zc_flags = 0;
 
-		ZCMD_COPY(zc_action_handle);
-		ZCMD_COPY(zc_cleanup_fd);
-		ZCMD_COPY(zc_simple);
+		FIELD_COPY(zc_action_handle);
+		FIELD_COPY(zc_cleanup_fd);
+		FIELD_COPY(zc_simple);
 		zc->zc_resumable = B_FALSE;
-		ZCMD_COPY(zc_sendobj);
-		ZCMD_COPY(zc_fromobj);
-		ZCMD_COPY(zc_createtxg);
-		ZCMD_COPY(zc_stat);
-#undef ZCMD_COPY
+		FIELD_COPY(zc_sendobj);
+		FIELD_COPY(zc_fromobj);
+		FIELD_COPY(zc_createtxg);
+		FIELD_COPY(zc_stat);
+#undef FIELD_COPY
 
 		break;
 
@@ -152,6 +247,8 @@ zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_
 		strlcpy(zc->zc_name, zcdm_c->zc_name, MAXPATHLEN);
 		strlcpy(zc->zc_value, zcdm_c->zc_value, MAXPATHLEN * 2);
 		strlcpy(zc->zc_string, zcdm_c->zc_string, MAXPATHLEN);
+
+#define FIELD_COPY(field) zc->field = zcdm_c->field
 		zc->zc_guid = zcdm_c->zc_guid;
 		zc->zc_nvlist_conf = zcdm_c->zc_nvlist_conf;
 		zc->zc_nvlist_conf_size = zcdm_c->zc_nvlist_conf_size;
@@ -181,12 +278,28 @@ zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_
 		zc->zc_fromobj = zcdm_c->zc_fromobj;
 		zc->zc_createtxg = zcdm_c->zc_createtxg;
 		zc->zc_stat = zcdm_c->zc_stat;
-
-		/* zc_inject_record doesn't change in libzfs_core */
-		zcdm_c->zc_inject_record = zc->zc_inject_record;
+		FIELD_COPY(zc_inject_record.zi_objset);
+		FIELD_COPY(zc_inject_record.zi_object);
+		FIELD_COPY(zc_inject_record.zi_start);
+		FIELD_COPY(zc_inject_record.zi_end);
+		FIELD_COPY(zc_inject_record.zi_guid);
+		FIELD_COPY(zc_inject_record.zi_level);
+		FIELD_COPY(zc_inject_record.zi_error);
+		FIELD_COPY(zc_inject_record.zi_type);
+		FIELD_COPY(zc_inject_record.zi_freq);
+		FIELD_COPY(zc_inject_record.zi_failfast);
+		strlcpy(zc->zc_inject_record.zi_func,
+		    resume_c->zc_inject_record.zi_func, MAXNAMELEN);
+		FIELD_COPY(zc_inject_record.zi_iotype);
+		FIELD_COPY(zc_inject_record.zi_duration);
+		FIELD_COPY(zc_inject_record.zi_timer);
+		zc->zc_inject_record.zi_nlanes = 1;
+		FIELD_COPY(zc_inject_record.zi_cmd);
+		FIELD_COPY(zc_inject_record.zi_pad);
 
 		/* we always assume zc_nvlist_dst_filled is true */
 		zc->zc_nvlist_dst_filled = B_TRUE;
+#undef FIELD_COPY
 		break;
 
 	case ZFS_CMD_COMPAT_V28:
@@ -255,6 +368,7 @@ zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_
 		    zc28_c->zc_inject_record.zi_duration;
 		zc->zc_inject_record.zi_timer =
 		    zc28_c->zc_inject_record.zi_timer;
+		zc->zc_inject_record.zi_nlanes = 1;
 		zc->zc_inject_record.zi_cmd = ZINJECT_UNINITIALIZED;
 		zc->zc_inject_record.zi_pad = 0;
 		break;
@@ -319,47 +433,121 @@ zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_
 	zfs_cmd_deadman_t *zcdm_c;
 	zfs_cmd_zcmd_t *zcmd_c;
 	zfs_cmd_edbp_t *edbp_c;
+	zfs_cmd_resume_t *resume_c;
 
 	switch (cflag) {
+	case ZFS_CMD_COMPAT_RESUME:
+		resume_c = (void *)addr;
+		strlcpy(resume_c->zc_name, zc->zc_name, MAXPATHLEN);
+		strlcpy(resume_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
+		strlcpy(resume_c->zc_string, zc->zc_string, MAXPATHLEN);
+
+#define FIELD_COPY(field) resume_c->field = zc->field
+		FIELD_COPY(zc_nvlist_src);
+		FIELD_COPY(zc_nvlist_src_size);
+		FIELD_COPY(zc_nvlist_dst);
+		FIELD_COPY(zc_nvlist_dst_size);
+		FIELD_COPY(zc_nvlist_dst_filled);
+		FIELD_COPY(zc_pad2);
+		FIELD_COPY(zc_history);
+		FIELD_COPY(zc_guid);
+		FIELD_COPY(zc_nvlist_conf);
+		FIELD_COPY(zc_nvlist_conf_size);
+		FIELD_COPY(zc_cookie);
+		FIELD_COPY(zc_objset_type);
+		FIELD_COPY(zc_perm_action);
+		FIELD_COPY(zc_history_len);
+		FIELD_COPY(zc_history_offset);
+		FIELD_COPY(zc_obj);
+		FIELD_COPY(zc_iflags);
+		FIELD_COPY(zc_share);
+		FIELD_COPY(zc_jailid);
+		FIELD_COPY(zc_objset_stats);
+		FIELD_COPY(zc_begin_record);
+		FIELD_COPY(zc_inject_record.zi_objset);
+		FIELD_COPY(zc_inject_record.zi_object);
+		FIELD_COPY(zc_inject_record.zi_start);
+		FIELD_COPY(zc_inject_record.zi_end);
+		FIELD_COPY(zc_inject_record.zi_guid);
+		FIELD_COPY(zc_inject_record.zi_level);
+		FIELD_COPY(zc_inject_record.zi_error);
+		FIELD_COPY(zc_inject_record.zi_type);
+		FIELD_COPY(zc_inject_record.zi_freq);
+		FIELD_COPY(zc_inject_record.zi_failfast);
+		strlcpy(resume_c->zc_inject_record.zi_func,
+		    zc->zc_inject_record.zi_func, MAXNAMELEN);
+		FIELD_COPY(zc_inject_record.zi_iotype);
+		FIELD_COPY(zc_inject_record.zi_duration);
+		FIELD_COPY(zc_inject_record.zi_timer);
+		FIELD_COPY(zc_inject_record.zi_cmd);
+		FIELD_COPY(zc_inject_record.zi_pad);
+		FIELD_COPY(zc_defer_destroy);
+		FIELD_COPY(zc_flags);
+		FIELD_COPY(zc_action_handle);
+		FIELD_COPY(zc_cleanup_fd);
+		FIELD_COPY(zc_simple);
+		FIELD_COPY(zc_sendobj);
+		FIELD_COPY(zc_fromobj);
+		FIELD_COPY(zc_createtxg);
+		FIELD_COPY(zc_stat);
+#undef FIELD_COPY
+		break;
+
 	case ZFS_CMD_COMPAT_EDBP:
 		edbp_c = (void *)addr;
 		strlcpy(edbp_c->zc_name, zc->zc_name, MAXPATHLEN);
 		strlcpy(edbp_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
 		strlcpy(edbp_c->zc_string, zc->zc_string, MAXPATHLEN);
 
-#define ZCMD_COPY(field) edbp_c->field = zc->field
-		ZCMD_COPY(zc_nvlist_src);
-		ZCMD_COPY(zc_nvlist_src_size);
-		ZCMD_COPY(zc_nvlist_dst);
-		ZCMD_COPY(zc_nvlist_dst_size);
-		ZCMD_COPY(zc_nvlist_dst_filled);
-		ZCMD_COPY(zc_pad2);
-		ZCMD_COPY(zc_history);
-		ZCMD_COPY(zc_guid);
-		ZCMD_COPY(zc_nvlist_conf);
-		ZCMD_COPY(zc_nvlist_conf_size);
-		ZCMD_COPY(zc_cookie);
-		ZCMD_COPY(zc_objset_type);
-		ZCMD_COPY(zc_perm_action);
-		ZCMD_COPY(zc_history_len);
-		ZCMD_COPY(zc_history_offset);
-		ZCMD_COPY(zc_obj);
-		ZCMD_COPY(zc_iflags);
-		ZCMD_COPY(zc_share);
-		ZCMD_COPY(zc_jailid);
-		ZCMD_COPY(zc_objset_stats);
+#define FIELD_COPY(field) edbp_c->field = zc->field
+		FIELD_COPY(zc_nvlist_src);
+		FIELD_COPY(zc_nvlist_src_size);
+		FIELD_COPY(zc_nvlist_dst);
+		FIELD_COPY(zc_nvlist_dst_size);
+		FIELD_COPY(zc_nvlist_dst_filled);
+		FIELD_COPY(zc_pad2);
+		FIELD_COPY(zc_history);
+		FIELD_COPY(zc_guid);
+		FIELD_COPY(zc_nvlist_conf);
+		FIELD_COPY(zc_nvlist_conf_size);
+		FIELD_COPY(zc_cookie);
+		FIELD_COPY(zc_objset_type);
+		FIELD_COPY(zc_perm_action);
+		FIELD_COPY(zc_history_len);
+		FIELD_COPY(zc_history_offset);
+		FIELD_COPY(zc_obj);
+		FIELD_COPY(zc_iflags);
+		FIELD_COPY(zc_share);
+		FIELD_COPY(zc_jailid);
+		FIELD_COPY(zc_objset_stats);
 		edbp_c->zc_begin_record = zc->zc_begin_record.drr_u.drr_begin;
-		ZCMD_COPY(zc_inject_record);
-		ZCMD_COPY(zc_defer_destroy);
-		ZCMD_COPY(zc_flags);
-		ZCMD_COPY(zc_action_handle);
-		ZCMD_COPY(zc_cleanup_fd);
-		ZCMD_COPY(zc_simple);
-		ZCMD_COPY(zc_sendobj);
-		ZCMD_COPY(zc_fromobj);
-		ZCMD_COPY(zc_createtxg);
-		ZCMD_COPY(zc_stat);
-#undef ZCMD_COPY
+		FIELD_COPY(zc_inject_record.zi_objset);
+		FIELD_COPY(zc_inject_record.zi_object);
+		FIELD_COPY(zc_inject_record.zi_start);
+		FIELD_COPY(zc_inject_record.zi_end);
+		FIELD_COPY(zc_inject_record.zi_guid);
+		FIELD_COPY(zc_inject_record.zi_level);
+		FIELD_COPY(zc_inject_record.zi_error);
+		FIELD_COPY(zc_inject_record.zi_type);
+		FIELD_COPY(zc_inject_record.zi_freq);
+		FIELD_COPY(zc_inject_record.zi_failfast);
+		strlcpy(resume_c->zc_inject_record.zi_func,
+		    zc->zc_inject_record.zi_func, MAXNAMELEN);
+		FIELD_COPY(zc_inject_record.zi_iotype);
+		FIELD_COPY(zc_inject_record.zi_duration);
+		FIELD_COPY(zc_inject_record.zi_timer);
+		FIELD_COPY(zc_inject_record.zi_cmd);
+		FIELD_COPY(zc_inject_record.zi_pad);
+		FIELD_COPY(zc_defer_destroy);
+		FIELD_COPY(zc_flags);
+		FIELD_COPY(zc_action_handle);
+		FIELD_COPY(zc_cleanup_fd);
+		FIELD_COPY(zc_simple);
+		FIELD_COPY(zc_sendobj);
+		FIELD_COPY(zc_fromobj);
+		FIELD_COPY(zc_createtxg);
+		FIELD_COPY(zc_stat);
+#undef FIELD_COPY
 		break;
 
 	case ZFS_CMD_COMPAT_ZCMD:
@@ -369,42 +557,58 @@ zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_
 		strlcpy(zcmd_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
 		strlcpy(zcmd_c->zc_string, zc->zc_string, MAXPATHLEN);
 
-#define ZCMD_COPY(field) zcmd_c->field = zc->field
-		ZCMD_COPY(zc_nvlist_src);
-		ZCMD_COPY(zc_nvlist_src_size);
-		ZCMD_COPY(zc_nvlist_dst);
-		ZCMD_COPY(zc_nvlist_dst_size);
-		ZCMD_COPY(zc_nvlist_dst_filled);
-		ZCMD_COPY(zc_pad2);
-		ZCMD_COPY(zc_history);
-		ZCMD_COPY(zc_guid);
-		ZCMD_COPY(zc_nvlist_conf);
-		ZCMD_COPY(zc_nvlist_conf_size);
-		ZCMD_COPY(zc_cookie);
-		ZCMD_COPY(zc_objset_type);
-		ZCMD_COPY(zc_perm_action);
-		ZCMD_COPY(zc_history_len);
-		ZCMD_COPY(zc_history_offset);
-		ZCMD_COPY(zc_obj);
-		ZCMD_COPY(zc_iflags);
-		ZCMD_COPY(zc_share);
-		ZCMD_COPY(zc_jailid);
-		ZCMD_COPY(zc_objset_stats);
+#define FIELD_COPY(field) zcmd_c->field = zc->field
+		FIELD_COPY(zc_nvlist_src);
+		FIELD_COPY(zc_nvlist_src_size);
+		FIELD_COPY(zc_nvlist_dst);
+		FIELD_COPY(zc_nvlist_dst_size);
+		FIELD_COPY(zc_nvlist_dst_filled);
+		FIELD_COPY(zc_pad2);
+		FIELD_COPY(zc_history);
+		FIELD_COPY(zc_guid);
+		FIELD_COPY(zc_nvlist_conf);
+		FIELD_COPY(zc_nvlist_conf_size);
+		FIELD_COPY(zc_cookie);
+		FIELD_COPY(zc_objset_type);
+		FIELD_COPY(zc_perm_action);
+		FIELD_COPY(zc_history_len);
+		FIELD_COPY(zc_history_offset);
+		FIELD_COPY(zc_obj);
+		FIELD_COPY(zc_iflags);
+		FIELD_COPY(zc_share);
+		FIELD_COPY(zc_jailid);
+		FIELD_COPY(zc_objset_stats);
 		zcmd_c->zc_begin_record = zc->zc_begin_record.drr_u.drr_begin;
-		ZCMD_COPY(zc_inject_record);
+		FIELD_COPY(zc_inject_record.zi_objset);
+		FIELD_COPY(zc_inject_record.zi_object);
+		FIELD_COPY(zc_inject_record.zi_start);
+		FIELD_COPY(zc_inject_record.zi_end);
+		FIELD_COPY(zc_inject_record.zi_guid);
+		FIELD_COPY(zc_inject_record.zi_level);
+		FIELD_COPY(zc_inject_record.zi_error);
+		FIELD_COPY(zc_inject_record.zi_type);
+		FIELD_COPY(zc_inject_record.zi_freq);
+		FIELD_COPY(zc_inject_record.zi_failfast);
+		strlcpy(resume_c->zc_inject_record.zi_func,
+		    zc->zc_inject_record.zi_func, MAXNAMELEN);
+		FIELD_COPY(zc_inject_record.zi_iotype);
+		FIELD_COPY(zc_inject_record.zi_duration);
+		FIELD_COPY(zc_inject_record.zi_timer);
+		FIELD_COPY(zc_inject_record.zi_cmd);
+		FIELD_COPY(zc_inject_record.zi_pad);
 
 		/* boolean_t -> uint32_t */
 		zcmd_c->zc_defer_destroy = (uint32_t)(zc->zc_defer_destroy);
 		zcmd_c->zc_temphold = 0;
 
-		ZCMD_COPY(zc_action_handle);
-		ZCMD_COPY(zc_cleanup_fd);
-		ZCMD_COPY(zc_simple);
-		ZCMD_COPY(zc_sendobj);
-		ZCMD_COPY(zc_fromobj);
-		ZCMD_COPY(zc_createtxg);
-		ZCMD_COPY(zc_stat);
-#undef ZCMD_COPY
+		FIELD_COPY(zc_action_handle);
+		FIELD_COPY(zc_cleanup_fd);
+		FIELD_COPY(zc_simple);
+		FIELD_COPY(zc_sendobj);
+		FIELD_COPY(zc_fromobj);
+		FIELD_COPY(zc_createtxg);
+		FIELD_COPY(zc_stat);
+#undef FIELD_COPY
 
 		break;
 
@@ -414,6 +618,8 @@ zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_
 		strlcpy(zcdm_c->zc_name, zc->zc_name, MAXPATHLEN);
 		strlcpy(zcdm_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
 		strlcpy(zcdm_c->zc_string, zc->zc_string, MAXPATHLEN);
+
+#define FIELD_COPY(field) zcdm_c->field = zc->field
 		zcdm_c->zc_guid = zc->zc_guid;
 		zcdm_c->zc_nvlist_conf = zc->zc_nvlist_conf;
 		zcdm_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
@@ -442,9 +648,24 @@ zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_
 		zcdm_c->zc_fromobj = zc->zc_fromobj;
 		zcdm_c->zc_createtxg = zc->zc_createtxg;
 		zcdm_c->zc_stat = zc->zc_stat;
-
-		/* zc_inject_record doesn't change in libzfs_core */
-		zc->zc_inject_record = zcdm_c->zc_inject_record;
+		FIELD_COPY(zc_inject_record.zi_objset);
+		FIELD_COPY(zc_inject_record.zi_object);
+		FIELD_COPY(zc_inject_record.zi_start);
+		FIELD_COPY(zc_inject_record.zi_end);
+		FIELD_COPY(zc_inject_record.zi_guid);
+		FIELD_COPY(zc_inject_record.zi_level);
+		FIELD_COPY(zc_inject_record.zi_error);
+		FIELD_COPY(zc_inject_record.zi_type);
+		FIELD_COPY(zc_inject_record.zi_freq);
+		FIELD_COPY(zc_inject_record.zi_failfast);
+		strlcpy(resume_c->zc_inject_record.zi_func,
+		    zc->zc_inject_record.zi_func, MAXNAMELEN);
+		FIELD_COPY(zc_inject_record.zi_iotype);
+		FIELD_COPY(zc_inject_record.zi_duration);
+		FIELD_COPY(zc_inject_record.zi_timer);
+		FIELD_COPY(zc_inject_record.zi_cmd);
+		FIELD_COPY(zc_inject_record.zi_pad);
+#undef FIELD_COPY
 #ifndef _KERNEL
 		if (request == ZFS_IOC_RECV)
 			strlcpy(zcdm_c->zc_top_ds,
@@ -766,6 +987,12 @@ zcmd_ioctl_compat(int fd, int request, z
 		zp.zfs_cmd_size = sizeof(zfs_cmd_t);
 		zp.zfs_ioctl_version = ZFS_IOCVER_CURRENT;
 		return (ioctl(fd, ncmd, &zp));
+	case ZFS_CMD_COMPAT_RESUME:
+		ncmd = _IOWR('Z', request, struct zfs_iocparm);
+		zp.zfs_cmd = (uint64_t)zc;
+		zp.zfs_cmd_size = sizeof(zfs_cmd_resume_t);
+		zp.zfs_ioctl_version = ZFS_IOCVER_RESUME;
+		return (ioctl(fd, ncmd, &zp));
 	case ZFS_CMD_COMPAT_EDBP:
 		ncmd = _IOWR('Z', request, struct zfs_iocparm);
 		zp.zfs_cmd = (uint64_t)zc;
@@ -876,7 +1103,8 @@ zfs_ioctl_compat_innvl(zfs_cmd_t *zc, nv
 	int err;
 
 	if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC ||
-	    cflag == ZFS_CMD_COMPAT_ZCMD || cflag == ZFS_CMD_COMPAT_EDBP)
+	    cflag == ZFS_CMD_COMPAT_ZCMD || cflag == ZFS_CMD_COMPAT_EDBP ||
+	    cflag == ZFS_CMD_COMPAT_RESUME)
 		goto out;
 
 	switch (vec) {
@@ -1028,7 +1256,8 @@ zfs_ioctl_compat_outnvl(zfs_cmd_t *zc, n
 	nvlist_t *tmpnvl;
 
 	if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC ||
-	    cflag == ZFS_CMD_COMPAT_ZCMD || cflag == ZFS_CMD_COMPAT_EDBP)
+	    cflag == ZFS_CMD_COMPAT_ZCMD || cflag == ZFS_CMD_COMPAT_EDBP ||
+	    cflag == ZFS_CMD_COMPAT_RESUME)
 		return (outnvl);
 
 	switch (vec) {

Modified: stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h	Mon Mar 21 00:09:56 2016	(r297107)
+++ stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h	Mon Mar 21 00:13:39 2016	(r297108)
@@ -53,7 +53,8 @@ extern "C" {
 #define	ZFS_IOCVER_ZCMD		3
 #define	ZFS_IOCVER_EDBP		4
 #define	ZFS_IOCVER_RESUME	5
-#define	ZFS_IOCVER_CURRENT	ZFS_IOCVER_RESUME
+#define	ZFS_IOCVER_INLANES	6
+#define	ZFS_IOCVER_CURRENT	ZFS_IOCVER_INLANES
 
 /* compatibility conversion flag */
 #define	ZFS_CMD_COMPAT_NONE	0
@@ -63,6 +64,7 @@ extern "C" {
 #define	ZFS_CMD_COMPAT_LZC	4
 #define	ZFS_CMD_COMPAT_ZCMD	5
 #define	ZFS_CMD_COMPAT_EDBP	6
+#define	ZFS_CMD_COMPAT_RESUME	7
 
 #define	ZFS_IOC_COMPAT_PASS	254
 #define	ZFS_IOC_COMPAT_FAIL	255
@@ -167,6 +169,25 @@ typedef struct zfs_cmd_v28 {
 	zfs_stat_t	zc_stat;
 } zfs_cmd_v28_t;
 
+typedef struct zinject_record_deadman {
+	uint64_t	zi_objset;
+	uint64_t	zi_object;
+	uint64_t	zi_start;
+	uint64_t	zi_end;
+	uint64_t	zi_guid;
+	uint32_t	zi_level;
+	uint32_t	zi_error;
+	uint64_t	zi_type;
+	uint32_t	zi_freq;
+	uint32_t	zi_failfast;
+	char		zi_func[MAXNAMELEN];
+	uint32_t	zi_iotype;
+	int32_t		zi_duration;
+	uint64_t	zi_timer;
+	uint32_t	zi_cmd;
+	uint32_t	zi_pad;
+} zinject_record_deadman_t;
+
 typedef struct zfs_cmd_deadman {
 	char		zc_name[MAXPATHLEN];
 	char		zc_value[MAXPATHLEN * 2];
@@ -192,7 +213,7 @@ typedef struct zfs_cmd_deadman {
 	dmu_objset_stats_t zc_objset_stats;
 	struct drr_begin zc_begin_record;
 	/* zc_inject_record doesn't change in libzfs_core */
-	zinject_record_t zc_inject_record;
+	zinject_record_deadman_t zc_inject_record;
 	boolean_t	zc_defer_destroy;
 	boolean_t	zc_temphold;
 	uint64_t	zc_action_handle;
@@ -235,7 +256,7 @@ typedef struct zfs_cmd_zcmd {
 	uint64_t	zc_jailid;
 	dmu_objset_stats_t zc_objset_stats;
 	struct drr_begin zc_begin_record;
-	zinject_record_t zc_inject_record;
+	zinject_record_deadman_t zc_inject_record;
 	boolean_t	zc_defer_destroy;
 	boolean_t	zc_temphold;
 	uint64_t	zc_action_handle;
@@ -278,7 +299,7 @@ typedef struct zfs_cmd_edbp {
 	uint64_t	zc_jailid;
 	dmu_objset_stats_t zc_objset_stats;
 	struct drr_begin zc_begin_record;
-	zinject_record_t zc_inject_record;
+	zinject_record_deadman_t zc_inject_record;
 	uint32_t	zc_defer_destroy;
 	uint32_t	zc_flags;
 	uint64_t	zc_action_handle;
@@ -291,6 +312,49 @@ typedef struct zfs_cmd_edbp {
 	zfs_stat_t	zc_stat;
 } zfs_cmd_edbp_t;
 
+typedef struct zfs_cmd_resume {
+	char		zc_name[MAXPATHLEN];	/* name of pool or dataset */
+	uint64_t	zc_nvlist_src;		/* really (char *) */
+	uint64_t	zc_nvlist_src_size;
+	uint64_t	zc_nvlist_dst;		/* really (char *) */
+	uint64_t	zc_nvlist_dst_size;
+	boolean_t	zc_nvlist_dst_filled;	/* put an nvlist in dst? */
+	int		zc_pad2;
+
+	/*
+	 * The following members are for legacy ioctls which haven't been
+	 * converted to the new method.
+	 */
+	uint64_t	zc_history;		/* really (char *) */
+	char		zc_value[MAXPATHLEN * 2];
+	char		zc_string[MAXNAMELEN];
+	uint64_t	zc_guid;
+	uint64_t	zc_nvlist_conf;		/* really (char *) */
+	uint64_t	zc_nvlist_conf_size;
+	uint64_t	zc_cookie;
+	uint64_t	zc_objset_type;
+	uint64_t	zc_perm_action;
+	uint64_t	zc_history_len;
+	uint64_t	zc_history_offset;
+	uint64_t	zc_obj;
+	uint64_t	zc_iflags;		/* internal to zfs(7fs) */
+	zfs_share_t	zc_share;
+	uint64_t	zc_jailid;
+	dmu_objset_stats_t zc_objset_stats;
+	dmu_replay_record_t zc_begin_record;
+	zinject_record_deadman_t zc_inject_record;
+	uint32_t	zc_defer_destroy;
+	uint32_t	zc_flags;
+	uint64_t	zc_action_handle;
+	int		zc_cleanup_fd;
+	uint8_t		zc_simple;
+	boolean_t	zc_resumable;
+	uint64_t	zc_sendobj;
+	uint64_t	zc_fromobj;
+	uint64_t	zc_createtxg;
+	zfs_stat_t	zc_stat;
+} zfs_cmd_resume_t;
+
 #ifdef _KERNEL
 unsigned static long zfs_ioctl_v15_to_v28[] = {
 	0,	/*  0 ZFS_IOC_POOL_CREATE */

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_context.h
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_context.h	Mon Mar 21 00:09:56 2016	(r297107)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_context.h	Mon Mar 21 00:13:39 2016	(r297108)
@@ -94,10 +94,8 @@ extern "C" {
 #include <sys/sunddi.h>
 #ifdef illumos
 #include <sys/cyclic.h>
-#include <sys/callo.h>
-#else	/* FreeBSD */
-#include <sys/callout.h>
 #endif
+#include <sys/callo.h>
 #include <sys/disp.h>
 #include <machine/stdarg.h>
 

Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h
==============================================================================
--- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h	Mon Mar 21 00:09:56 2016	(r297107)
+++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h	Mon Mar 21 00:13:39 2016	(r297108)
@@ -308,6 +308,7 @@ typedef struct zinject_record {
 	uint32_t	zi_iotype;
 	int32_t		zi_duration;
 	uint64_t	zi_timer;
+	uint64_t	zi_nlanes;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201603210013.u2L0DdJl034841>