zfs_ioctl_compat.c revision 307054
1279377Simp/*
2279377Simp * CDDL HEADER START
3279377Simp *
4279377Simp * The contents of this file are subject to the terms of the
5279377Simp * Common Development and Distribution License (the "License").
6279377Simp * You may not use this file except in compliance with the License.
7279377Simp *
8279377Simp * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9279377Simp * or http://www.opensolaris.org/os/licensing.
10279377Simp * See the License for the specific language governing permissions
11279377Simp * and limitations under the License.
12279377Simp *
13279377Simp * When distributing Covered Code, include this CDDL HEADER in each
14279377Simp * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15279377Simp * If applicable, add the following below this CDDL HEADER, with the
16279377Simp * fields enclosed by brackets "[]" replaced with your own identifying
17279377Simp * information: Portions Copyright [yyyy] [name of copyright owner]
18279377Simp *
19279377Simp * CDDL HEADER END
20279377Simp */
21279377Simp/*
22279377Simp * Copyright 2013 Xin Li <delphij@FreeBSD.org>. All rights reserved.
23279377Simp * Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
24279377Simp * Portions Copyright 2005, 2010, Oracle and/or its affiliates.
25279377Simp * All rights reserved.
26279377Simp * Use is subject to license terms.
27279377Simp */
28279377Simp
29279377Simp#include <sys/types.h>
30279377Simp#include <sys/param.h>
31279377Simp#include <sys/cred.h>
32279377Simp#include <sys/dmu.h>
33279377Simp#include <sys/zio.h>
34279377Simp#include <sys/nvpair.h>
35279377Simp#include <sys/dsl_deleg.h>
36279377Simp#include <sys/zfs_ioctl.h>
37279377Simp#include "zfs_namecheck.h"
38279377Simp#include "zfs_ioctl_compat.h"
39279377Simp
40279377Simpstatic int zfs_version_ioctl = ZFS_IOCVER_CURRENT;
41279377SimpSYSCTL_DECL(_vfs_zfs_version);
42279377SimpSYSCTL_INT(_vfs_zfs_version, OID_AUTO, ioctl, CTLFLAG_RD, &zfs_version_ioctl,
43279377Simp    0, "ZFS_IOCTL_VERSION");
44279377Simp
45279377Simp/*
46279377Simp * FreeBSD zfs_cmd compatibility with older binaries
47279377Simp * appropriately remap/extend the zfs_cmd_t structure
48279377Simp */
49279377Simpvoid
50279377Simpzfs_cmd_compat_get(zfs_cmd_t *zc, caddr_t addr, const int cflag)
51279377Simp{
52279377Simp	zfs_cmd_v15_t *zc_c;
53279377Simp	zfs_cmd_v28_t *zc28_c;
54279377Simp	zfs_cmd_deadman_t *zcdm_c;
55279377Simp	zfs_cmd_zcmd_t *zcmd_c;
56279377Simp	zfs_cmd_edbp_t *edbp_c;
57279377Simp	zfs_cmd_resume_t *resume_c;
58279377Simp	zfs_cmd_inlanes_t *inlanes_c;
59279377Simp
60279377Simp	switch (cflag) {
61279377Simp	case ZFS_CMD_COMPAT_INLANES:
62279377Simp		inlanes_c = (void *)addr;
63279377Simp		/* zc */
64279377Simp		strlcpy(zc->zc_name, inlanes_c->zc_name, MAXPATHLEN);
65279377Simp		strlcpy(zc->zc_value, inlanes_c->zc_value, MAXPATHLEN * 2);
66279377Simp		strlcpy(zc->zc_string, inlanes_c->zc_string, MAXPATHLEN);
67279377Simp
68279377Simp#define FIELD_COPY(field) zc->field = inlanes_c->field
69279377Simp		FIELD_COPY(zc_nvlist_src);
70279377Simp		FIELD_COPY(zc_nvlist_src_size);
71279377Simp		FIELD_COPY(zc_nvlist_dst);
72279377Simp		FIELD_COPY(zc_nvlist_dst_size);
73279377Simp		FIELD_COPY(zc_nvlist_dst_filled);
74279377Simp		FIELD_COPY(zc_pad2);
75279377Simp		FIELD_COPY(zc_history);
76279377Simp		FIELD_COPY(zc_guid);
77279377Simp		FIELD_COPY(zc_nvlist_conf);
78279377Simp		FIELD_COPY(zc_nvlist_conf_size);
79279377Simp		FIELD_COPY(zc_cookie);
80279377Simp		FIELD_COPY(zc_objset_type);
81279377Simp		FIELD_COPY(zc_perm_action);
82279377Simp		FIELD_COPY(zc_history_len);
83279377Simp		FIELD_COPY(zc_history_offset);
84279377Simp		FIELD_COPY(zc_obj);
85279377Simp		FIELD_COPY(zc_iflags);
86279377Simp		FIELD_COPY(zc_share);
87279377Simp		FIELD_COPY(zc_jailid);
88279377Simp		FIELD_COPY(zc_objset_stats);
89279377Simp		FIELD_COPY(zc_begin_record);
90279377Simp		FIELD_COPY(zc_inject_record);
91279377Simp		FIELD_COPY(zc_defer_destroy);
92279377Simp		FIELD_COPY(zc_flags);
93279377Simp		FIELD_COPY(zc_action_handle);
94279377Simp		FIELD_COPY(zc_cleanup_fd);
95279377Simp		FIELD_COPY(zc_simple);
96279377Simp		FIELD_COPY(zc_resumable);
97279377Simp		FIELD_COPY(zc_sendobj);
98279377Simp		FIELD_COPY(zc_fromobj);
99279377Simp		FIELD_COPY(zc_createtxg);
100279377Simp		FIELD_COPY(zc_stat);
101279377Simp#undef FIELD_COPY
102279377Simp		break;
103279377Simp
104279377Simp	case ZFS_CMD_COMPAT_RESUME:
105279377Simp		resume_c = (void *)addr;
106279377Simp		/* zc */
107279377Simp		strlcpy(zc->zc_name, resume_c->zc_name, MAXPATHLEN);
108279377Simp		strlcpy(zc->zc_value, resume_c->zc_value, MAXPATHLEN * 2);
109279377Simp		strlcpy(zc->zc_string, resume_c->zc_string, MAXPATHLEN);
110279377Simp
111279377Simp#define FIELD_COPY(field) zc->field = resume_c->field
112279377Simp		FIELD_COPY(zc_nvlist_src);
113279377Simp		FIELD_COPY(zc_nvlist_src_size);
114279377Simp		FIELD_COPY(zc_nvlist_dst);
115279377Simp		FIELD_COPY(zc_nvlist_dst_size);
116279377Simp		FIELD_COPY(zc_nvlist_dst_filled);
117279377Simp		FIELD_COPY(zc_pad2);
118279377Simp		FIELD_COPY(zc_history);
119279377Simp		FIELD_COPY(zc_guid);
120279377Simp		FIELD_COPY(zc_nvlist_conf);
121279377Simp		FIELD_COPY(zc_nvlist_conf_size);
122279377Simp		FIELD_COPY(zc_cookie);
123279377Simp		FIELD_COPY(zc_objset_type);
124279377Simp		FIELD_COPY(zc_perm_action);
125279377Simp		FIELD_COPY(zc_history_len);
126279377Simp		FIELD_COPY(zc_history_offset);
127279377Simp		FIELD_COPY(zc_obj);
128279377Simp		FIELD_COPY(zc_iflags);
129279377Simp		FIELD_COPY(zc_share);
130279377Simp		FIELD_COPY(zc_jailid);
131279377Simp		FIELD_COPY(zc_objset_stats);
132279377Simp		FIELD_COPY(zc_begin_record);
133279377Simp		FIELD_COPY(zc_inject_record.zi_objset);
134279377Simp		FIELD_COPY(zc_inject_record.zi_object);
135279377Simp		FIELD_COPY(zc_inject_record.zi_start);
136279377Simp		FIELD_COPY(zc_inject_record.zi_end);
137279377Simp		FIELD_COPY(zc_inject_record.zi_guid);
138279377Simp		FIELD_COPY(zc_inject_record.zi_level);
139279377Simp		FIELD_COPY(zc_inject_record.zi_error);
140279377Simp		FIELD_COPY(zc_inject_record.zi_type);
141279377Simp		FIELD_COPY(zc_inject_record.zi_freq);
142279377Simp		FIELD_COPY(zc_inject_record.zi_failfast);
143279377Simp		strlcpy(zc->zc_inject_record.zi_func,
144279377Simp		    resume_c->zc_inject_record.zi_func, MAXNAMELEN);
145279377Simp		FIELD_COPY(zc_inject_record.zi_iotype);
146279377Simp		FIELD_COPY(zc_inject_record.zi_duration);
147279377Simp		FIELD_COPY(zc_inject_record.zi_timer);
148279377Simp		zc->zc_inject_record.zi_nlanes = 1;
149279377Simp		FIELD_COPY(zc_inject_record.zi_cmd);
150279377Simp		FIELD_COPY(zc_inject_record.zi_pad);
151279377Simp		FIELD_COPY(zc_defer_destroy);
152279377Simp		FIELD_COPY(zc_flags);
153279377Simp		FIELD_COPY(zc_action_handle);
154279377Simp		FIELD_COPY(zc_cleanup_fd);
155279377Simp		FIELD_COPY(zc_simple);
156279377Simp		FIELD_COPY(zc_resumable);
157279377Simp		FIELD_COPY(zc_sendobj);
158279377Simp		FIELD_COPY(zc_fromobj);
159279377Simp		FIELD_COPY(zc_createtxg);
160279377Simp		FIELD_COPY(zc_stat);
161279377Simp#undef FIELD_COPY
162279377Simp		break;
163279377Simp
164279377Simp	case ZFS_CMD_COMPAT_EDBP:
165279377Simp		edbp_c = (void *)addr;
166279377Simp		/* zc */
167279377Simp		strlcpy(zc->zc_name, edbp_c->zc_name, MAXPATHLEN);
168279377Simp		strlcpy(zc->zc_value, edbp_c->zc_value, MAXPATHLEN * 2);
169279377Simp		strlcpy(zc->zc_string, edbp_c->zc_string, MAXPATHLEN);
170279377Simp
171279377Simp#define FIELD_COPY(field) zc->field = edbp_c->field
172279377Simp		FIELD_COPY(zc_nvlist_src);
173279377Simp		FIELD_COPY(zc_nvlist_src_size);
174279377Simp		FIELD_COPY(zc_nvlist_dst);
175279377Simp		FIELD_COPY(zc_nvlist_dst_size);
176279377Simp		FIELD_COPY(zc_nvlist_dst_filled);
177279377Simp		FIELD_COPY(zc_pad2);
178279377Simp		FIELD_COPY(zc_history);
179279377Simp		FIELD_COPY(zc_guid);
180279377Simp		FIELD_COPY(zc_nvlist_conf);
181279377Simp		FIELD_COPY(zc_nvlist_conf_size);
182279377Simp		FIELD_COPY(zc_cookie);
183279377Simp		FIELD_COPY(zc_objset_type);
184279377Simp		FIELD_COPY(zc_perm_action);
185279377Simp		FIELD_COPY(zc_history_len);
186279377Simp		FIELD_COPY(zc_history_offset);
187279377Simp		FIELD_COPY(zc_obj);
188279377Simp		FIELD_COPY(zc_iflags);
189279377Simp		FIELD_COPY(zc_share);
190279377Simp		FIELD_COPY(zc_jailid);
191279377Simp		FIELD_COPY(zc_objset_stats);
192279377Simp		zc->zc_begin_record.drr_u.drr_begin = edbp_c->zc_begin_record;
193279377Simp		FIELD_COPY(zc_inject_record.zi_objset);
194279377Simp		FIELD_COPY(zc_inject_record.zi_object);
195279377Simp		FIELD_COPY(zc_inject_record.zi_start);
196279377Simp		FIELD_COPY(zc_inject_record.zi_end);
197279377Simp		FIELD_COPY(zc_inject_record.zi_guid);
198279377Simp		FIELD_COPY(zc_inject_record.zi_level);
199279377Simp		FIELD_COPY(zc_inject_record.zi_error);
200279377Simp		FIELD_COPY(zc_inject_record.zi_type);
201279377Simp		FIELD_COPY(zc_inject_record.zi_freq);
202279377Simp		FIELD_COPY(zc_inject_record.zi_failfast);
203279377Simp		strlcpy(zc->zc_inject_record.zi_func,
204279377Simp		    edbp_c->zc_inject_record.zi_func, MAXNAMELEN);
205279377Simp		FIELD_COPY(zc_inject_record.zi_iotype);
206279377Simp		FIELD_COPY(zc_inject_record.zi_duration);
207279377Simp		FIELD_COPY(zc_inject_record.zi_timer);
208279377Simp		zc->zc_inject_record.zi_nlanes = 1;
209279377Simp		FIELD_COPY(zc_inject_record.zi_cmd);
210279377Simp		FIELD_COPY(zc_inject_record.zi_pad);
211279377Simp		FIELD_COPY(zc_defer_destroy);
212279377Simp		FIELD_COPY(zc_flags);
213279377Simp		FIELD_COPY(zc_action_handle);
214279377Simp		FIELD_COPY(zc_cleanup_fd);
215279377Simp		FIELD_COPY(zc_simple);
216279377Simp		zc->zc_resumable = B_FALSE;
217279377Simp		FIELD_COPY(zc_sendobj);
218279377Simp		FIELD_COPY(zc_fromobj);
219279377Simp		FIELD_COPY(zc_createtxg);
220279377Simp		FIELD_COPY(zc_stat);
221279377Simp#undef FIELD_COPY
222279377Simp		break;
223279377Simp
224279377Simp	case ZFS_CMD_COMPAT_ZCMD:
225279377Simp		zcmd_c = (void *)addr;
226279377Simp		/* zc */
227279377Simp		strlcpy(zc->zc_name, zcmd_c->zc_name, MAXPATHLEN);
228279377Simp		strlcpy(zc->zc_value, zcmd_c->zc_value, MAXPATHLEN * 2);
229279377Simp		strlcpy(zc->zc_string, zcmd_c->zc_string, MAXPATHLEN);
230279377Simp
231279377Simp#define FIELD_COPY(field) zc->field = zcmd_c->field
232279377Simp		FIELD_COPY(zc_nvlist_src);
233279377Simp		FIELD_COPY(zc_nvlist_src_size);
234279377Simp		FIELD_COPY(zc_nvlist_dst);
235279377Simp		FIELD_COPY(zc_nvlist_dst_size);
236279377Simp		FIELD_COPY(zc_nvlist_dst_filled);
237279377Simp		FIELD_COPY(zc_pad2);
238279377Simp		FIELD_COPY(zc_history);
239279377Simp		FIELD_COPY(zc_guid);
240279377Simp		FIELD_COPY(zc_nvlist_conf);
241279377Simp		FIELD_COPY(zc_nvlist_conf_size);
242279377Simp		FIELD_COPY(zc_cookie);
243279377Simp		FIELD_COPY(zc_objset_type);
244279377Simp		FIELD_COPY(zc_perm_action);
245279377Simp		FIELD_COPY(zc_history_len);
246279377Simp		FIELD_COPY(zc_history_offset);
247279377Simp		FIELD_COPY(zc_obj);
248279377Simp		FIELD_COPY(zc_iflags);
249279377Simp		FIELD_COPY(zc_share);
250279377Simp		FIELD_COPY(zc_jailid);
251279377Simp		FIELD_COPY(zc_objset_stats);
252279377Simp		zc->zc_begin_record.drr_u.drr_begin = zcmd_c->zc_begin_record;
253279377Simp		FIELD_COPY(zc_inject_record.zi_objset);
254279377Simp		FIELD_COPY(zc_inject_record.zi_object);
255		FIELD_COPY(zc_inject_record.zi_start);
256		FIELD_COPY(zc_inject_record.zi_end);
257		FIELD_COPY(zc_inject_record.zi_guid);
258		FIELD_COPY(zc_inject_record.zi_level);
259		FIELD_COPY(zc_inject_record.zi_error);
260		FIELD_COPY(zc_inject_record.zi_type);
261		FIELD_COPY(zc_inject_record.zi_freq);
262		FIELD_COPY(zc_inject_record.zi_failfast);
263		strlcpy(zc->zc_inject_record.zi_func,
264		    zcmd_c->zc_inject_record.zi_func, MAXNAMELEN);
265		FIELD_COPY(zc_inject_record.zi_iotype);
266		FIELD_COPY(zc_inject_record.zi_duration);
267		FIELD_COPY(zc_inject_record.zi_timer);
268		zc->zc_inject_record.zi_nlanes = 1;
269		FIELD_COPY(zc_inject_record.zi_cmd);
270		FIELD_COPY(zc_inject_record.zi_pad);
271
272		/* boolean_t -> uint32_t */
273		zc->zc_defer_destroy = (uint32_t)(zcmd_c->zc_defer_destroy);
274		zc->zc_flags = 0;
275
276		FIELD_COPY(zc_action_handle);
277		FIELD_COPY(zc_cleanup_fd);
278		FIELD_COPY(zc_simple);
279		zc->zc_resumable = B_FALSE;
280		FIELD_COPY(zc_sendobj);
281		FIELD_COPY(zc_fromobj);
282		FIELD_COPY(zc_createtxg);
283		FIELD_COPY(zc_stat);
284#undef FIELD_COPY
285
286		break;
287
288	case ZFS_CMD_COMPAT_DEADMAN:
289		zcdm_c = (void *)addr;
290		/* zc */
291		strlcpy(zc->zc_name, zcdm_c->zc_name, MAXPATHLEN);
292		strlcpy(zc->zc_value, zcdm_c->zc_value, MAXPATHLEN * 2);
293		strlcpy(zc->zc_string, zcdm_c->zc_string, MAXPATHLEN);
294
295#define FIELD_COPY(field) zc->field = zcdm_c->field
296		zc->zc_guid = zcdm_c->zc_guid;
297		zc->zc_nvlist_conf = zcdm_c->zc_nvlist_conf;
298		zc->zc_nvlist_conf_size = zcdm_c->zc_nvlist_conf_size;
299		zc->zc_nvlist_src = zcdm_c->zc_nvlist_src;
300		zc->zc_nvlist_src_size = zcdm_c->zc_nvlist_src_size;
301		zc->zc_nvlist_dst = zcdm_c->zc_nvlist_dst;
302		zc->zc_nvlist_dst_size = zcdm_c->zc_nvlist_dst_size;
303		zc->zc_cookie = zcdm_c->zc_cookie;
304		zc->zc_objset_type = zcdm_c->zc_objset_type;
305		zc->zc_perm_action = zcdm_c->zc_perm_action;
306		zc->zc_history = zcdm_c->zc_history;
307		zc->zc_history_len = zcdm_c->zc_history_len;
308		zc->zc_history_offset = zcdm_c->zc_history_offset;
309		zc->zc_obj = zcdm_c->zc_obj;
310		zc->zc_iflags = zcdm_c->zc_iflags;
311		zc->zc_share = zcdm_c->zc_share;
312		zc->zc_jailid = zcdm_c->zc_jailid;
313		zc->zc_objset_stats = zcdm_c->zc_objset_stats;
314		zc->zc_begin_record.drr_u.drr_begin = zcdm_c->zc_begin_record;
315		zc->zc_defer_destroy = zcdm_c->zc_defer_destroy;
316		(void)zcdm_c->zc_temphold;
317		zc->zc_action_handle = zcdm_c->zc_action_handle;
318		zc->zc_cleanup_fd = zcdm_c->zc_cleanup_fd;
319		zc->zc_simple = zcdm_c->zc_simple;
320		zc->zc_resumable = B_FALSE;
321		zc->zc_sendobj = zcdm_c->zc_sendobj;
322		zc->zc_fromobj = zcdm_c->zc_fromobj;
323		zc->zc_createtxg = zcdm_c->zc_createtxg;
324		zc->zc_stat = zcdm_c->zc_stat;
325		FIELD_COPY(zc_inject_record.zi_objset);
326		FIELD_COPY(zc_inject_record.zi_object);
327		FIELD_COPY(zc_inject_record.zi_start);
328		FIELD_COPY(zc_inject_record.zi_end);
329		FIELD_COPY(zc_inject_record.zi_guid);
330		FIELD_COPY(zc_inject_record.zi_level);
331		FIELD_COPY(zc_inject_record.zi_error);
332		FIELD_COPY(zc_inject_record.zi_type);
333		FIELD_COPY(zc_inject_record.zi_freq);
334		FIELD_COPY(zc_inject_record.zi_failfast);
335		strlcpy(zc->zc_inject_record.zi_func,
336		    resume_c->zc_inject_record.zi_func, MAXNAMELEN);
337		FIELD_COPY(zc_inject_record.zi_iotype);
338		FIELD_COPY(zc_inject_record.zi_duration);
339		FIELD_COPY(zc_inject_record.zi_timer);
340		zc->zc_inject_record.zi_nlanes = 1;
341		FIELD_COPY(zc_inject_record.zi_cmd);
342		FIELD_COPY(zc_inject_record.zi_pad);
343
344		/* we always assume zc_nvlist_dst_filled is true */
345		zc->zc_nvlist_dst_filled = B_TRUE;
346#undef FIELD_COPY
347		break;
348
349	case ZFS_CMD_COMPAT_V28:
350		zc28_c = (void *)addr;
351
352		/* zc */
353		strlcpy(zc->zc_name, zc28_c->zc_name, MAXPATHLEN);
354		strlcpy(zc->zc_value, zc28_c->zc_value, MAXPATHLEN * 2);
355		strlcpy(zc->zc_string, zc28_c->zc_string, MAXPATHLEN);
356		zc->zc_guid = zc28_c->zc_guid;
357		zc->zc_nvlist_conf = zc28_c->zc_nvlist_conf;
358		zc->zc_nvlist_conf_size = zc28_c->zc_nvlist_conf_size;
359		zc->zc_nvlist_src = zc28_c->zc_nvlist_src;
360		zc->zc_nvlist_src_size = zc28_c->zc_nvlist_src_size;
361		zc->zc_nvlist_dst = zc28_c->zc_nvlist_dst;
362		zc->zc_nvlist_dst_size = zc28_c->zc_nvlist_dst_size;
363		zc->zc_cookie = zc28_c->zc_cookie;
364		zc->zc_objset_type = zc28_c->zc_objset_type;
365		zc->zc_perm_action = zc28_c->zc_perm_action;
366		zc->zc_history = zc28_c->zc_history;
367		zc->zc_history_len = zc28_c->zc_history_len;
368		zc->zc_history_offset = zc28_c->zc_history_offset;
369		zc->zc_obj = zc28_c->zc_obj;
370		zc->zc_iflags = zc28_c->zc_iflags;
371		zc->zc_share = zc28_c->zc_share;
372		zc->zc_jailid = zc28_c->zc_jailid;
373		zc->zc_objset_stats = zc28_c->zc_objset_stats;
374		zc->zc_begin_record.drr_u.drr_begin = zc28_c->zc_begin_record;
375		zc->zc_defer_destroy = zc28_c->zc_defer_destroy;
376		(void)zc28_c->zc_temphold;
377		zc->zc_action_handle = zc28_c->zc_action_handle;
378		zc->zc_cleanup_fd = zc28_c->zc_cleanup_fd;
379		zc->zc_simple = zc28_c->zc_simple;
380		zc->zc_resumable = B_FALSE;
381		zc->zc_sendobj = zc28_c->zc_sendobj;
382		zc->zc_fromobj = zc28_c->zc_fromobj;
383		zc->zc_createtxg = zc28_c->zc_createtxg;
384		zc->zc_stat = zc28_c->zc_stat;
385
386		/* zc->zc_inject_record */
387		zc->zc_inject_record.zi_objset =
388		    zc28_c->zc_inject_record.zi_objset;
389		zc->zc_inject_record.zi_object =
390		    zc28_c->zc_inject_record.zi_object;
391		zc->zc_inject_record.zi_start =
392		    zc28_c->zc_inject_record.zi_start;
393		zc->zc_inject_record.zi_end =
394		    zc28_c->zc_inject_record.zi_end;
395		zc->zc_inject_record.zi_guid =
396		    zc28_c->zc_inject_record.zi_guid;
397		zc->zc_inject_record.zi_level =
398		    zc28_c->zc_inject_record.zi_level;
399		zc->zc_inject_record.zi_error =
400		    zc28_c->zc_inject_record.zi_error;
401		zc->zc_inject_record.zi_type =
402		    zc28_c->zc_inject_record.zi_type;
403		zc->zc_inject_record.zi_freq =
404		    zc28_c->zc_inject_record.zi_freq;
405		zc->zc_inject_record.zi_failfast =
406		    zc28_c->zc_inject_record.zi_failfast;
407		strlcpy(zc->zc_inject_record.zi_func,
408		    zc28_c->zc_inject_record.zi_func, MAXNAMELEN);
409		zc->zc_inject_record.zi_iotype =
410		    zc28_c->zc_inject_record.zi_iotype;
411		zc->zc_inject_record.zi_duration =
412		    zc28_c->zc_inject_record.zi_duration;
413		zc->zc_inject_record.zi_timer =
414		    zc28_c->zc_inject_record.zi_timer;
415		zc->zc_inject_record.zi_nlanes = 1;
416		zc->zc_inject_record.zi_cmd = ZINJECT_UNINITIALIZED;
417		zc->zc_inject_record.zi_pad = 0;
418		break;
419
420	case ZFS_CMD_COMPAT_V15:
421		zc_c = (void *)addr;
422
423		/* zc */
424		strlcpy(zc->zc_name, zc_c->zc_name, MAXPATHLEN);
425		strlcpy(zc->zc_value, zc_c->zc_value, MAXPATHLEN);
426		strlcpy(zc->zc_string, zc_c->zc_string, MAXPATHLEN);
427		zc->zc_guid = zc_c->zc_guid;
428		zc->zc_nvlist_conf = zc_c->zc_nvlist_conf;
429		zc->zc_nvlist_conf_size = zc_c->zc_nvlist_conf_size;
430		zc->zc_nvlist_src = zc_c->zc_nvlist_src;
431		zc->zc_nvlist_src_size = zc_c->zc_nvlist_src_size;
432		zc->zc_nvlist_dst = zc_c->zc_nvlist_dst;
433		zc->zc_nvlist_dst_size = zc_c->zc_nvlist_dst_size;
434		zc->zc_cookie = zc_c->zc_cookie;
435		zc->zc_objset_type = zc_c->zc_objset_type;
436		zc->zc_perm_action = zc_c->zc_perm_action;
437		zc->zc_history = zc_c->zc_history;
438		zc->zc_history_len = zc_c->zc_history_len;
439		zc->zc_history_offset = zc_c->zc_history_offset;
440		zc->zc_obj = zc_c->zc_obj;
441		zc->zc_share = zc_c->zc_share;
442		zc->zc_jailid = zc_c->zc_jailid;
443		zc->zc_objset_stats = zc_c->zc_objset_stats;
444		zc->zc_begin_record.drr_u.drr_begin = zc_c->zc_begin_record;
445
446		/* zc->zc_inject_record */
447		zc->zc_inject_record.zi_objset =
448		    zc_c->zc_inject_record.zi_objset;
449		zc->zc_inject_record.zi_object =
450		    zc_c->zc_inject_record.zi_object;
451		zc->zc_inject_record.zi_start =
452		    zc_c->zc_inject_record.zi_start;
453		zc->zc_inject_record.zi_end =
454		    zc_c->zc_inject_record.zi_end;
455		zc->zc_inject_record.zi_guid =
456		    zc_c->zc_inject_record.zi_guid;
457		zc->zc_inject_record.zi_level =
458		    zc_c->zc_inject_record.zi_level;
459		zc->zc_inject_record.zi_error =
460		    zc_c->zc_inject_record.zi_error;
461		zc->zc_inject_record.zi_type =
462		    zc_c->zc_inject_record.zi_type;
463		zc->zc_inject_record.zi_freq =
464		    zc_c->zc_inject_record.zi_freq;
465		zc->zc_inject_record.zi_failfast =
466		    zc_c->zc_inject_record.zi_failfast;
467		break;
468	}
469}
470
471void
472zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_t addr, const int request,
473    const int cflag)
474{
475	zfs_cmd_v15_t *zc_c;
476	zfs_cmd_v28_t *zc28_c;
477	zfs_cmd_deadman_t *zcdm_c;
478	zfs_cmd_zcmd_t *zcmd_c;
479	zfs_cmd_edbp_t *edbp_c;
480	zfs_cmd_resume_t *resume_c;
481	zfs_cmd_inlanes_t *inlanes_c;
482
483	switch (cflag) {
484	case ZFS_CMD_COMPAT_INLANES:
485		inlanes_c = (void *)addr;
486		strlcpy(inlanes_c->zc_name, zc->zc_name, MAXPATHLEN);
487		strlcpy(inlanes_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
488		strlcpy(inlanes_c->zc_string, zc->zc_string, MAXPATHLEN);
489
490#define FIELD_COPY(field) inlanes_c->field = zc->field
491		FIELD_COPY(zc_nvlist_src);
492		FIELD_COPY(zc_nvlist_src_size);
493		FIELD_COPY(zc_nvlist_dst);
494		FIELD_COPY(zc_nvlist_dst_size);
495		FIELD_COPY(zc_nvlist_dst_filled);
496		FIELD_COPY(zc_pad2);
497		FIELD_COPY(zc_history);
498		FIELD_COPY(zc_guid);
499		FIELD_COPY(zc_nvlist_conf);
500		FIELD_COPY(zc_nvlist_conf_size);
501		FIELD_COPY(zc_cookie);
502		FIELD_COPY(zc_objset_type);
503		FIELD_COPY(zc_perm_action);
504		FIELD_COPY(zc_history_len);
505		FIELD_COPY(zc_history_offset);
506		FIELD_COPY(zc_obj);
507		FIELD_COPY(zc_iflags);
508		FIELD_COPY(zc_share);
509		FIELD_COPY(zc_jailid);
510		FIELD_COPY(zc_objset_stats);
511		FIELD_COPY(zc_begin_record);
512		FIELD_COPY(zc_inject_record);
513		FIELD_COPY(zc_defer_destroy);
514		FIELD_COPY(zc_flags);
515		FIELD_COPY(zc_action_handle);
516		FIELD_COPY(zc_cleanup_fd);
517		FIELD_COPY(zc_simple);
518		FIELD_COPY(zc_sendobj);
519		FIELD_COPY(zc_fromobj);
520		FIELD_COPY(zc_createtxg);
521		FIELD_COPY(zc_stat);
522#undef FIELD_COPY
523		break;
524
525	case ZFS_CMD_COMPAT_RESUME:
526		resume_c = (void *)addr;
527		strlcpy(resume_c->zc_name, zc->zc_name, MAXPATHLEN);
528		strlcpy(resume_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
529		strlcpy(resume_c->zc_string, zc->zc_string, MAXPATHLEN);
530
531#define FIELD_COPY(field) resume_c->field = zc->field
532		FIELD_COPY(zc_nvlist_src);
533		FIELD_COPY(zc_nvlist_src_size);
534		FIELD_COPY(zc_nvlist_dst);
535		FIELD_COPY(zc_nvlist_dst_size);
536		FIELD_COPY(zc_nvlist_dst_filled);
537		FIELD_COPY(zc_pad2);
538		FIELD_COPY(zc_history);
539		FIELD_COPY(zc_guid);
540		FIELD_COPY(zc_nvlist_conf);
541		FIELD_COPY(zc_nvlist_conf_size);
542		FIELD_COPY(zc_cookie);
543		FIELD_COPY(zc_objset_type);
544		FIELD_COPY(zc_perm_action);
545		FIELD_COPY(zc_history_len);
546		FIELD_COPY(zc_history_offset);
547		FIELD_COPY(zc_obj);
548		FIELD_COPY(zc_iflags);
549		FIELD_COPY(zc_share);
550		FIELD_COPY(zc_jailid);
551		FIELD_COPY(zc_objset_stats);
552		FIELD_COPY(zc_begin_record);
553		FIELD_COPY(zc_inject_record.zi_objset);
554		FIELD_COPY(zc_inject_record.zi_object);
555		FIELD_COPY(zc_inject_record.zi_start);
556		FIELD_COPY(zc_inject_record.zi_end);
557		FIELD_COPY(zc_inject_record.zi_guid);
558		FIELD_COPY(zc_inject_record.zi_level);
559		FIELD_COPY(zc_inject_record.zi_error);
560		FIELD_COPY(zc_inject_record.zi_type);
561		FIELD_COPY(zc_inject_record.zi_freq);
562		FIELD_COPY(zc_inject_record.zi_failfast);
563		strlcpy(resume_c->zc_inject_record.zi_func,
564		    zc->zc_inject_record.zi_func, MAXNAMELEN);
565		FIELD_COPY(zc_inject_record.zi_iotype);
566		FIELD_COPY(zc_inject_record.zi_duration);
567		FIELD_COPY(zc_inject_record.zi_timer);
568		FIELD_COPY(zc_inject_record.zi_cmd);
569		FIELD_COPY(zc_inject_record.zi_pad);
570		FIELD_COPY(zc_defer_destroy);
571		FIELD_COPY(zc_flags);
572		FIELD_COPY(zc_action_handle);
573		FIELD_COPY(zc_cleanup_fd);
574		FIELD_COPY(zc_simple);
575		FIELD_COPY(zc_sendobj);
576		FIELD_COPY(zc_fromobj);
577		FIELD_COPY(zc_createtxg);
578		FIELD_COPY(zc_stat);
579#undef FIELD_COPY
580		break;
581
582	case ZFS_CMD_COMPAT_EDBP:
583		edbp_c = (void *)addr;
584		strlcpy(edbp_c->zc_name, zc->zc_name, MAXPATHLEN);
585		strlcpy(edbp_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
586		strlcpy(edbp_c->zc_string, zc->zc_string, MAXPATHLEN);
587
588#define FIELD_COPY(field) edbp_c->field = zc->field
589		FIELD_COPY(zc_nvlist_src);
590		FIELD_COPY(zc_nvlist_src_size);
591		FIELD_COPY(zc_nvlist_dst);
592		FIELD_COPY(zc_nvlist_dst_size);
593		FIELD_COPY(zc_nvlist_dst_filled);
594		FIELD_COPY(zc_pad2);
595		FIELD_COPY(zc_history);
596		FIELD_COPY(zc_guid);
597		FIELD_COPY(zc_nvlist_conf);
598		FIELD_COPY(zc_nvlist_conf_size);
599		FIELD_COPY(zc_cookie);
600		FIELD_COPY(zc_objset_type);
601		FIELD_COPY(zc_perm_action);
602		FIELD_COPY(zc_history_len);
603		FIELD_COPY(zc_history_offset);
604		FIELD_COPY(zc_obj);
605		FIELD_COPY(zc_iflags);
606		FIELD_COPY(zc_share);
607		FIELD_COPY(zc_jailid);
608		FIELD_COPY(zc_objset_stats);
609		edbp_c->zc_begin_record = zc->zc_begin_record.drr_u.drr_begin;
610		FIELD_COPY(zc_inject_record.zi_objset);
611		FIELD_COPY(zc_inject_record.zi_object);
612		FIELD_COPY(zc_inject_record.zi_start);
613		FIELD_COPY(zc_inject_record.zi_end);
614		FIELD_COPY(zc_inject_record.zi_guid);
615		FIELD_COPY(zc_inject_record.zi_level);
616		FIELD_COPY(zc_inject_record.zi_error);
617		FIELD_COPY(zc_inject_record.zi_type);
618		FIELD_COPY(zc_inject_record.zi_freq);
619		FIELD_COPY(zc_inject_record.zi_failfast);
620		strlcpy(resume_c->zc_inject_record.zi_func,
621		    zc->zc_inject_record.zi_func, MAXNAMELEN);
622		FIELD_COPY(zc_inject_record.zi_iotype);
623		FIELD_COPY(zc_inject_record.zi_duration);
624		FIELD_COPY(zc_inject_record.zi_timer);
625		FIELD_COPY(zc_inject_record.zi_cmd);
626		FIELD_COPY(zc_inject_record.zi_pad);
627		FIELD_COPY(zc_defer_destroy);
628		FIELD_COPY(zc_flags);
629		FIELD_COPY(zc_action_handle);
630		FIELD_COPY(zc_cleanup_fd);
631		FIELD_COPY(zc_simple);
632		FIELD_COPY(zc_sendobj);
633		FIELD_COPY(zc_fromobj);
634		FIELD_COPY(zc_createtxg);
635		FIELD_COPY(zc_stat);
636#undef FIELD_COPY
637		break;
638
639	case ZFS_CMD_COMPAT_ZCMD:
640		zcmd_c = (void *)addr;
641		/* zc */
642		strlcpy(zcmd_c->zc_name, zc->zc_name, MAXPATHLEN);
643		strlcpy(zcmd_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
644		strlcpy(zcmd_c->zc_string, zc->zc_string, MAXPATHLEN);
645
646#define FIELD_COPY(field) zcmd_c->field = zc->field
647		FIELD_COPY(zc_nvlist_src);
648		FIELD_COPY(zc_nvlist_src_size);
649		FIELD_COPY(zc_nvlist_dst);
650		FIELD_COPY(zc_nvlist_dst_size);
651		FIELD_COPY(zc_nvlist_dst_filled);
652		FIELD_COPY(zc_pad2);
653		FIELD_COPY(zc_history);
654		FIELD_COPY(zc_guid);
655		FIELD_COPY(zc_nvlist_conf);
656		FIELD_COPY(zc_nvlist_conf_size);
657		FIELD_COPY(zc_cookie);
658		FIELD_COPY(zc_objset_type);
659		FIELD_COPY(zc_perm_action);
660		FIELD_COPY(zc_history_len);
661		FIELD_COPY(zc_history_offset);
662		FIELD_COPY(zc_obj);
663		FIELD_COPY(zc_iflags);
664		FIELD_COPY(zc_share);
665		FIELD_COPY(zc_jailid);
666		FIELD_COPY(zc_objset_stats);
667		zcmd_c->zc_begin_record = zc->zc_begin_record.drr_u.drr_begin;
668		FIELD_COPY(zc_inject_record.zi_objset);
669		FIELD_COPY(zc_inject_record.zi_object);
670		FIELD_COPY(zc_inject_record.zi_start);
671		FIELD_COPY(zc_inject_record.zi_end);
672		FIELD_COPY(zc_inject_record.zi_guid);
673		FIELD_COPY(zc_inject_record.zi_level);
674		FIELD_COPY(zc_inject_record.zi_error);
675		FIELD_COPY(zc_inject_record.zi_type);
676		FIELD_COPY(zc_inject_record.zi_freq);
677		FIELD_COPY(zc_inject_record.zi_failfast);
678		strlcpy(resume_c->zc_inject_record.zi_func,
679		    zc->zc_inject_record.zi_func, MAXNAMELEN);
680		FIELD_COPY(zc_inject_record.zi_iotype);
681		FIELD_COPY(zc_inject_record.zi_duration);
682		FIELD_COPY(zc_inject_record.zi_timer);
683		FIELD_COPY(zc_inject_record.zi_cmd);
684		FIELD_COPY(zc_inject_record.zi_pad);
685
686		/* boolean_t -> uint32_t */
687		zcmd_c->zc_defer_destroy = (uint32_t)(zc->zc_defer_destroy);
688		zcmd_c->zc_temphold = 0;
689
690		FIELD_COPY(zc_action_handle);
691		FIELD_COPY(zc_cleanup_fd);
692		FIELD_COPY(zc_simple);
693		FIELD_COPY(zc_sendobj);
694		FIELD_COPY(zc_fromobj);
695		FIELD_COPY(zc_createtxg);
696		FIELD_COPY(zc_stat);
697#undef FIELD_COPY
698
699		break;
700
701	case ZFS_CMD_COMPAT_DEADMAN:
702		zcdm_c = (void *)addr;
703
704		strlcpy(zcdm_c->zc_name, zc->zc_name, MAXPATHLEN);
705		strlcpy(zcdm_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
706		strlcpy(zcdm_c->zc_string, zc->zc_string, MAXPATHLEN);
707
708#define FIELD_COPY(field) zcdm_c->field = zc->field
709		zcdm_c->zc_guid = zc->zc_guid;
710		zcdm_c->zc_nvlist_conf = zc->zc_nvlist_conf;
711		zcdm_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
712		zcdm_c->zc_nvlist_src = zc->zc_nvlist_src;
713		zcdm_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
714		zcdm_c->zc_nvlist_dst = zc->zc_nvlist_dst;
715		zcdm_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
716		zcdm_c->zc_cookie = zc->zc_cookie;
717		zcdm_c->zc_objset_type = zc->zc_objset_type;
718		zcdm_c->zc_perm_action = zc->zc_perm_action;
719		zcdm_c->zc_history = zc->zc_history;
720		zcdm_c->zc_history_len = zc->zc_history_len;
721		zcdm_c->zc_history_offset = zc->zc_history_offset;
722		zcdm_c->zc_obj = zc->zc_obj;
723		zcdm_c->zc_iflags = zc->zc_iflags;
724		zcdm_c->zc_share = zc->zc_share;
725		zcdm_c->zc_jailid = zc->zc_jailid;
726		zcdm_c->zc_objset_stats = zc->zc_objset_stats;
727		zcdm_c->zc_begin_record = zc->zc_begin_record.drr_u.drr_begin;
728		zcdm_c->zc_defer_destroy = zc->zc_defer_destroy;
729		zcdm_c->zc_temphold = 0;
730		zcdm_c->zc_action_handle = zc->zc_action_handle;
731		zcdm_c->zc_cleanup_fd = zc->zc_cleanup_fd;
732		zcdm_c->zc_simple = zc->zc_simple;
733		zcdm_c->zc_sendobj = zc->zc_sendobj;
734		zcdm_c->zc_fromobj = zc->zc_fromobj;
735		zcdm_c->zc_createtxg = zc->zc_createtxg;
736		zcdm_c->zc_stat = zc->zc_stat;
737		FIELD_COPY(zc_inject_record.zi_objset);
738		FIELD_COPY(zc_inject_record.zi_object);
739		FIELD_COPY(zc_inject_record.zi_start);
740		FIELD_COPY(zc_inject_record.zi_end);
741		FIELD_COPY(zc_inject_record.zi_guid);
742		FIELD_COPY(zc_inject_record.zi_level);
743		FIELD_COPY(zc_inject_record.zi_error);
744		FIELD_COPY(zc_inject_record.zi_type);
745		FIELD_COPY(zc_inject_record.zi_freq);
746		FIELD_COPY(zc_inject_record.zi_failfast);
747		strlcpy(resume_c->zc_inject_record.zi_func,
748		    zc->zc_inject_record.zi_func, MAXNAMELEN);
749		FIELD_COPY(zc_inject_record.zi_iotype);
750		FIELD_COPY(zc_inject_record.zi_duration);
751		FIELD_COPY(zc_inject_record.zi_timer);
752		FIELD_COPY(zc_inject_record.zi_cmd);
753		FIELD_COPY(zc_inject_record.zi_pad);
754#undef FIELD_COPY
755#ifndef _KERNEL
756		if (request == ZFS_IOC_RECV)
757			strlcpy(zcdm_c->zc_top_ds,
758			    zc->zc_value + strlen(zc->zc_value) + 1,
759			    (MAXPATHLEN * 2) - strlen(zc->zc_value) - 1);
760#endif
761		break;
762
763	case ZFS_CMD_COMPAT_V28:
764		zc28_c = (void *)addr;
765
766		strlcpy(zc28_c->zc_name, zc->zc_name, MAXPATHLEN);
767		strlcpy(zc28_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
768		strlcpy(zc28_c->zc_string, zc->zc_string, MAXPATHLEN);
769		zc28_c->zc_guid = zc->zc_guid;
770		zc28_c->zc_nvlist_conf = zc->zc_nvlist_conf;
771		zc28_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
772		zc28_c->zc_nvlist_src = zc->zc_nvlist_src;
773		zc28_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
774		zc28_c->zc_nvlist_dst = zc->zc_nvlist_dst;
775		zc28_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
776		zc28_c->zc_cookie = zc->zc_cookie;
777		zc28_c->zc_objset_type = zc->zc_objset_type;
778		zc28_c->zc_perm_action = zc->zc_perm_action;
779		zc28_c->zc_history = zc->zc_history;
780		zc28_c->zc_history_len = zc->zc_history_len;
781		zc28_c->zc_history_offset = zc->zc_history_offset;
782		zc28_c->zc_obj = zc->zc_obj;
783		zc28_c->zc_iflags = zc->zc_iflags;
784		zc28_c->zc_share = zc->zc_share;
785		zc28_c->zc_jailid = zc->zc_jailid;
786		zc28_c->zc_objset_stats = zc->zc_objset_stats;
787		zc28_c->zc_begin_record = zc->zc_begin_record.drr_u.drr_begin;
788		zc28_c->zc_defer_destroy = zc->zc_defer_destroy;
789		zc28_c->zc_temphold = 0;
790		zc28_c->zc_action_handle = zc->zc_action_handle;
791		zc28_c->zc_cleanup_fd = zc->zc_cleanup_fd;
792		zc28_c->zc_simple = zc->zc_simple;
793		zc28_c->zc_sendobj = zc->zc_sendobj;
794		zc28_c->zc_fromobj = zc->zc_fromobj;
795		zc28_c->zc_createtxg = zc->zc_createtxg;
796		zc28_c->zc_stat = zc->zc_stat;
797#ifndef _KERNEL
798		if (request == ZFS_IOC_RECV)
799			strlcpy(zc28_c->zc_top_ds,
800			    zc->zc_value + strlen(zc->zc_value) + 1,
801			    MAXPATHLEN * 2 - strlen(zc->zc_value) - 1);
802#endif
803		/* zc_inject_record */
804		zc28_c->zc_inject_record.zi_objset =
805		    zc->zc_inject_record.zi_objset;
806		zc28_c->zc_inject_record.zi_object =
807		    zc->zc_inject_record.zi_object;
808		zc28_c->zc_inject_record.zi_start =
809		    zc->zc_inject_record.zi_start;
810		zc28_c->zc_inject_record.zi_end =
811		    zc->zc_inject_record.zi_end;
812		zc28_c->zc_inject_record.zi_guid =
813		    zc->zc_inject_record.zi_guid;
814		zc28_c->zc_inject_record.zi_level =
815		    zc->zc_inject_record.zi_level;
816		zc28_c->zc_inject_record.zi_error =
817		    zc->zc_inject_record.zi_error;
818		zc28_c->zc_inject_record.zi_type =
819		    zc->zc_inject_record.zi_type;
820		zc28_c->zc_inject_record.zi_freq =
821		    zc->zc_inject_record.zi_freq;
822		zc28_c->zc_inject_record.zi_failfast =
823		    zc->zc_inject_record.zi_failfast;
824		strlcpy(zc28_c->zc_inject_record.zi_func,
825		    zc->zc_inject_record.zi_func, MAXNAMELEN);
826		zc28_c->zc_inject_record.zi_iotype =
827		    zc->zc_inject_record.zi_iotype;
828		zc28_c->zc_inject_record.zi_duration =
829		    zc->zc_inject_record.zi_duration;
830		zc28_c->zc_inject_record.zi_timer =
831		    zc->zc_inject_record.zi_timer;
832		break;
833
834	case ZFS_CMD_COMPAT_V15:
835		zc_c = (void *)addr;
836
837		/* zc */
838		strlcpy(zc_c->zc_name, zc->zc_name, MAXPATHLEN);
839		strlcpy(zc_c->zc_value, zc->zc_value, MAXPATHLEN);
840		strlcpy(zc_c->zc_string, zc->zc_string, MAXPATHLEN);
841		zc_c->zc_guid = zc->zc_guid;
842		zc_c->zc_nvlist_conf = zc->zc_nvlist_conf;
843		zc_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
844		zc_c->zc_nvlist_src = zc->zc_nvlist_src;
845		zc_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
846		zc_c->zc_nvlist_dst = zc->zc_nvlist_dst;
847		zc_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
848		zc_c->zc_cookie = zc->zc_cookie;
849		zc_c->zc_objset_type = zc->zc_objset_type;
850		zc_c->zc_perm_action = zc->zc_perm_action;
851		zc_c->zc_history = zc->zc_history;
852		zc_c->zc_history_len = zc->zc_history_len;
853		zc_c->zc_history_offset = zc->zc_history_offset;
854		zc_c->zc_obj = zc->zc_obj;
855		zc_c->zc_share = zc->zc_share;
856		zc_c->zc_jailid = zc->zc_jailid;
857		zc_c->zc_objset_stats = zc->zc_objset_stats;
858		zc_c->zc_begin_record = zc->zc_begin_record.drr_u.drr_begin;
859
860		/* zc_inject_record */
861		zc_c->zc_inject_record.zi_objset =
862		    zc->zc_inject_record.zi_objset;
863		zc_c->zc_inject_record.zi_object =
864		    zc->zc_inject_record.zi_object;
865		zc_c->zc_inject_record.zi_start =
866		    zc->zc_inject_record.zi_start;
867		zc_c->zc_inject_record.zi_end =
868		    zc->zc_inject_record.zi_end;
869		zc_c->zc_inject_record.zi_guid =
870		    zc->zc_inject_record.zi_guid;
871		zc_c->zc_inject_record.zi_level =
872		    zc->zc_inject_record.zi_level;
873		zc_c->zc_inject_record.zi_error =
874		    zc->zc_inject_record.zi_error;
875		zc_c->zc_inject_record.zi_type =
876		    zc->zc_inject_record.zi_type;
877		zc_c->zc_inject_record.zi_freq =
878		    zc->zc_inject_record.zi_freq;
879		zc_c->zc_inject_record.zi_failfast =
880		    zc->zc_inject_record.zi_failfast;
881
882		break;
883	}
884}
885
886static int
887zfs_ioctl_compat_get_nvlist(uint64_t nvl, size_t size, int iflag,
888    nvlist_t **nvp)
889{
890	char *packed;
891	int error;
892	nvlist_t *list = NULL;
893
894	/*
895	 * Read in and unpack the user-supplied nvlist.
896	 */
897	if (size == 0)
898		return (EINVAL);
899
900#ifdef _KERNEL
901	packed = kmem_alloc(size, KM_SLEEP);
902	if ((error = ddi_copyin((void *)(uintptr_t)nvl, packed, size,
903	    iflag)) != 0) {
904		kmem_free(packed, size);
905		return (error);
906	}
907#else
908	packed = (void *)(uintptr_t)nvl;
909#endif
910
911	error = nvlist_unpack(packed, size, &list, 0);
912
913#ifdef _KERNEL
914	kmem_free(packed, size);
915#endif
916
917	if (error != 0)
918		return (error);
919
920	*nvp = list;
921	return (0);
922}
923
924static int
925zfs_ioctl_compat_put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
926{
927	char *packed = NULL;
928	int error = 0;
929	size_t size;
930
931	VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0);
932
933#ifdef _KERNEL
934	packed = kmem_alloc(size, KM_SLEEP);
935	VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
936	    KM_SLEEP) == 0);
937
938	if (ddi_copyout(packed,
939	    (void *)(uintptr_t)zc->zc_nvlist_dst, size, zc->zc_iflags) != 0)
940		error = EFAULT;
941	kmem_free(packed, size);
942#else
943	packed = (void *)(uintptr_t)zc->zc_nvlist_dst;
944	VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
945	    0) == 0);
946#endif
947
948	zc->zc_nvlist_dst_size = size;
949	return (error);
950}
951
952static void
953zfs_ioctl_compat_fix_stats_nvlist(nvlist_t *nvl)
954{
955	nvlist_t **child;
956	nvlist_t *nvroot = NULL;
957	vdev_stat_t *vs;
958	uint_t c, children, nelem;
959
960	if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_CHILDREN,
961	    &child, &children) == 0) {
962		for (c = 0; c < children; c++) {
963			zfs_ioctl_compat_fix_stats_nvlist(child[c]);
964		}
965	}
966
967	if (nvlist_lookup_nvlist(nvl, ZPOOL_CONFIG_VDEV_TREE,
968	    &nvroot) == 0)
969		zfs_ioctl_compat_fix_stats_nvlist(nvroot);
970#ifdef _KERNEL
971	if ((nvlist_lookup_uint64_array(nvl, ZPOOL_CONFIG_VDEV_STATS,
972#else
973	if ((nvlist_lookup_uint64_array(nvl, "stats",
974#endif
975
976	    (uint64_t **)&vs, &nelem) == 0)) {
977		nvlist_add_uint64_array(nvl,
978#ifdef _KERNEL
979		    "stats",
980#else
981		    ZPOOL_CONFIG_VDEV_STATS,
982#endif
983		    (uint64_t *)vs, nelem);
984#ifdef _KERNEL
985		nvlist_remove(nvl, ZPOOL_CONFIG_VDEV_STATS,
986#else
987		nvlist_remove(nvl, "stats",
988#endif
989		    DATA_TYPE_UINT64_ARRAY);
990	}
991}
992
993static int
994zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int nc)
995{
996	nvlist_t *nv, *nvp = NULL;
997	nvpair_t *elem;
998	int error;
999
1000	if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst,
1001	    zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
1002		return (error);
1003
1004	if (nc == 5) { /* ZFS_IOC_POOL_STATS */
1005		elem = NULL;
1006		while ((elem = nvlist_next_nvpair(nv, elem)) != NULL) {
1007			if (nvpair_value_nvlist(elem, &nvp) == 0)
1008				zfs_ioctl_compat_fix_stats_nvlist(nvp);
1009		}
1010		elem = NULL;
1011	} else
1012		zfs_ioctl_compat_fix_stats_nvlist(nv);
1013
1014	error = zfs_ioctl_compat_put_nvlist(zc, nv);
1015
1016	nvlist_free(nv);
1017
1018	return (error);
1019}
1020
1021static int
1022zfs_ioctl_compat_pool_get_props(zfs_cmd_t *zc)
1023{
1024	nvlist_t *nv, *nva = NULL;
1025	int error;
1026
1027	if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst,
1028	    zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
1029		return (error);
1030
1031#ifdef _KERNEL
1032	if (nvlist_lookup_nvlist(nv, "allocated", &nva) == 0) {
1033		nvlist_add_nvlist(nv, "used", nva);
1034		nvlist_remove(nv, "allocated", DATA_TYPE_NVLIST);
1035	}
1036
1037	if (nvlist_lookup_nvlist(nv, "free", &nva) == 0) {
1038		nvlist_add_nvlist(nv, "available", nva);
1039		nvlist_remove(nv, "free", DATA_TYPE_NVLIST);
1040	}
1041#else
1042	if (nvlist_lookup_nvlist(nv, "used", &nva) == 0) {
1043		nvlist_add_nvlist(nv, "allocated", nva);
1044		nvlist_remove(nv, "used", DATA_TYPE_NVLIST);
1045	}
1046
1047	if (nvlist_lookup_nvlist(nv, "available", &nva) == 0) {
1048		nvlist_add_nvlist(nv, "free", nva);
1049		nvlist_remove(nv, "available", DATA_TYPE_NVLIST);
1050	}
1051#endif
1052
1053	error = zfs_ioctl_compat_put_nvlist(zc, nv);
1054
1055	nvlist_free(nv);
1056
1057	return (error);
1058}
1059
1060#ifndef _KERNEL
1061int
1062zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag)
1063{
1064	int nc, ret;
1065	void *zc_c;
1066	unsigned long ncmd;
1067	zfs_iocparm_t zp;
1068
1069	switch (cflag) {
1070	case ZFS_CMD_COMPAT_NONE:
1071		ncmd = _IOWR('Z', request, struct zfs_iocparm);
1072		zp.zfs_cmd = (uint64_t)zc;
1073		zp.zfs_cmd_size = sizeof(zfs_cmd_t);
1074		zp.zfs_ioctl_version = ZFS_IOCVER_CURRENT;
1075		return (ioctl(fd, ncmd, &zp));
1076	case ZFS_CMD_COMPAT_INLANES:
1077		ncmd = _IOWR('Z', request, struct zfs_iocparm);
1078		zp.zfs_cmd = (uint64_t)zc;
1079		zp.zfs_cmd_size = sizeof(zfs_cmd_inlanes_t);
1080		zp.zfs_ioctl_version = ZFS_IOCVER_INLANES;
1081		return (ioctl(fd, ncmd, &zp));
1082	case ZFS_CMD_COMPAT_RESUME:
1083		ncmd = _IOWR('Z', request, struct zfs_iocparm);
1084		zp.zfs_cmd = (uint64_t)zc;
1085		zp.zfs_cmd_size = sizeof(zfs_cmd_resume_t);
1086		zp.zfs_ioctl_version = ZFS_IOCVER_RESUME;
1087		return (ioctl(fd, ncmd, &zp));
1088	case ZFS_CMD_COMPAT_EDBP:
1089		ncmd = _IOWR('Z', request, struct zfs_iocparm);
1090		zp.zfs_cmd = (uint64_t)zc;
1091		zp.zfs_cmd_size = sizeof(zfs_cmd_edbp_t);
1092		zp.zfs_ioctl_version = ZFS_IOCVER_EDBP;
1093		return (ioctl(fd, ncmd, &zp));
1094	case ZFS_CMD_COMPAT_ZCMD:
1095		ncmd = _IOWR('Z', request, struct zfs_iocparm);
1096		zp.zfs_cmd = (uint64_t)zc;
1097		zp.zfs_cmd_size = sizeof(zfs_cmd_zcmd_t);
1098		zp.zfs_ioctl_version = ZFS_IOCVER_ZCMD;
1099		return (ioctl(fd, ncmd, &zp));
1100	case ZFS_CMD_COMPAT_LZC:
1101		ncmd = _IOWR('Z', request, struct zfs_cmd);
1102		return (ioctl(fd, ncmd, zc));
1103	case ZFS_CMD_COMPAT_DEADMAN:
1104		zc_c = malloc(sizeof(zfs_cmd_deadman_t));
1105		ncmd = _IOWR('Z', request, struct zfs_cmd_deadman);
1106		break;
1107	case ZFS_CMD_COMPAT_V28:
1108		zc_c = malloc(sizeof(zfs_cmd_v28_t));
1109		ncmd = _IOWR('Z', request, struct zfs_cmd_v28);
1110		break;
1111	case ZFS_CMD_COMPAT_V15:
1112		nc = zfs_ioctl_v28_to_v15[request];
1113		zc_c = malloc(sizeof(zfs_cmd_v15_t));
1114		ncmd = _IOWR('Z', nc, struct zfs_cmd_v15);
1115		break;
1116	default:
1117		return (EINVAL);
1118	}
1119
1120	if (ZFS_IOCREQ(ncmd) == ZFS_IOC_COMPAT_FAIL)
1121		return (ENOTSUP);
1122
1123	zfs_cmd_compat_put(zc, (caddr_t)zc_c, request, cflag);
1124
1125	ret = ioctl(fd, ncmd, zc_c);
1126	if (cflag == ZFS_CMD_COMPAT_V15 &&
1127	    nc == ZFS_IOC_POOL_IMPORT)
1128		ret = ioctl(fd, _IOWR('Z', ZFS_IOC_POOL_CONFIGS,
1129		    struct zfs_cmd_v15), zc_c);
1130	zfs_cmd_compat_get(zc, (caddr_t)zc_c, cflag);
1131	free(zc_c);
1132
1133	if (cflag == ZFS_CMD_COMPAT_V15) {
1134		switch (nc) {
1135		case ZFS_IOC_POOL_IMPORT:
1136		case ZFS_IOC_POOL_CONFIGS:
1137		case ZFS_IOC_POOL_STATS:
1138		case ZFS_IOC_POOL_TRYIMPORT:
1139			zfs_ioctl_compat_fix_stats(zc, nc);
1140			break;
1141		case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
1142			zfs_ioctl_compat_pool_get_props(zc);
1143			break;
1144		}
1145	}
1146
1147	return (ret);
1148}
1149#else /* _KERNEL */
1150int
1151zfs_ioctl_compat_pre(zfs_cmd_t *zc, int *vec, const int cflag)
1152{
1153	int error = 0;
1154
1155	/* are we creating a clone? */
1156	if (*vec == ZFS_IOC_CREATE && zc->zc_value[0] != '\0')
1157		*vec = ZFS_IOC_CLONE;
1158
1159	if (cflag == ZFS_CMD_COMPAT_V15) {
1160		switch (*vec) {
1161
1162		case 7: /* ZFS_IOC_POOL_SCRUB (v15) */
1163			zc->zc_cookie = POOL_SCAN_SCRUB;
1164			break;
1165		}
1166	}
1167
1168	return (error);
1169}
1170
1171void
1172zfs_ioctl_compat_post(zfs_cmd_t *zc, int vec, const int cflag)
1173{
1174	if (cflag == ZFS_CMD_COMPAT_V15) {
1175		switch (vec) {
1176		case ZFS_IOC_POOL_CONFIGS:
1177		case ZFS_IOC_POOL_STATS:
1178		case ZFS_IOC_POOL_TRYIMPORT:
1179			zfs_ioctl_compat_fix_stats(zc, vec);
1180			break;
1181		case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
1182			zfs_ioctl_compat_pool_get_props(zc);
1183			break;
1184		}
1185	}
1186}
1187
1188nvlist_t *
1189zfs_ioctl_compat_innvl(zfs_cmd_t *zc, nvlist_t * innvl, const int vec,
1190    const int cflag)
1191{
1192	nvlist_t *nvl, *tmpnvl, *hnvl;
1193	nvpair_t *elem;
1194	char *poolname, *snapname;
1195	int err;
1196
1197	if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC ||
1198	    cflag == ZFS_CMD_COMPAT_ZCMD || cflag == ZFS_CMD_COMPAT_EDBP ||
1199	    cflag == ZFS_CMD_COMPAT_RESUME || cflag == ZFS_CMD_COMPAT_INLANES)
1200		goto out;
1201
1202	switch (vec) {
1203	case ZFS_IOC_CREATE:
1204		nvl = fnvlist_alloc();
1205		fnvlist_add_int32(nvl, "type", zc->zc_objset_type);
1206		if (innvl != NULL) {
1207			fnvlist_add_nvlist(nvl, "props", innvl);
1208			nvlist_free(innvl);
1209		}
1210		return (nvl);
1211	break;
1212	case ZFS_IOC_CLONE:
1213		nvl = fnvlist_alloc();
1214		fnvlist_add_string(nvl, "origin", zc->zc_value);
1215		if (innvl != NULL) {
1216			fnvlist_add_nvlist(nvl, "props", innvl);
1217			nvlist_free(innvl);
1218		}
1219		return (nvl);
1220	break;
1221	case ZFS_IOC_SNAPSHOT:
1222		if (innvl == NULL)
1223			goto out;
1224		nvl = fnvlist_alloc();
1225		fnvlist_add_nvlist(nvl, "props", innvl);
1226		tmpnvl = fnvlist_alloc();
1227		snapname = kmem_asprintf("%s@%s", zc->zc_name, zc->zc_value);
1228		fnvlist_add_boolean(tmpnvl, snapname);
1229		kmem_free(snapname, strlen(snapname + 1));
1230		/* check if we are doing a recursive snapshot */
1231		if (zc->zc_cookie)
1232			dmu_get_recursive_snaps_nvl(zc->zc_name, zc->zc_value,
1233			    tmpnvl);
1234		fnvlist_add_nvlist(nvl, "snaps", tmpnvl);
1235		fnvlist_free(tmpnvl);
1236		nvlist_free(innvl);
1237		/* strip dataset part from zc->zc_name */
1238		zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
1239		return (nvl);
1240	break;
1241	case ZFS_IOC_SPACE_SNAPS:
1242		nvl = fnvlist_alloc();
1243		fnvlist_add_string(nvl, "firstsnap", zc->zc_value);
1244		if (innvl != NULL)
1245			nvlist_free(innvl);
1246		return (nvl);
1247	break;
1248	case ZFS_IOC_DESTROY_SNAPS:
1249		if (innvl == NULL && cflag == ZFS_CMD_COMPAT_DEADMAN)
1250			goto out;
1251		nvl = fnvlist_alloc();
1252		if (innvl != NULL) {
1253			fnvlist_add_nvlist(nvl, "snaps", innvl);
1254		} else {
1255			/*
1256			 * We are probably called by even older binaries,
1257			 * allocate and populate nvlist with recursive
1258			 * snapshots
1259			 */
1260			if (zfs_component_namecheck(zc->zc_value, NULL,
1261			    NULL) == 0) {
1262				tmpnvl = fnvlist_alloc();
1263				if (dmu_get_recursive_snaps_nvl(zc->zc_name,
1264				    zc->zc_value, tmpnvl) == 0)
1265					fnvlist_add_nvlist(nvl, "snaps",
1266					    tmpnvl);
1267				nvlist_free(tmpnvl);
1268			}
1269		}
1270		if (innvl != NULL)
1271			nvlist_free(innvl);
1272		/* strip dataset part from zc->zc_name */
1273		zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
1274		return (nvl);
1275	break;
1276	case ZFS_IOC_HOLD:
1277		nvl = fnvlist_alloc();
1278		tmpnvl = fnvlist_alloc();
1279		if (zc->zc_cleanup_fd != -1)
1280			fnvlist_add_int32(nvl, "cleanup_fd",
1281			    (int32_t)zc->zc_cleanup_fd);
1282		if (zc->zc_cookie) {
1283			hnvl = fnvlist_alloc();
1284			if (dmu_get_recursive_snaps_nvl(zc->zc_name,
1285			    zc->zc_value, hnvl) == 0) {
1286				elem = NULL;
1287				while ((elem = nvlist_next_nvpair(hnvl,
1288				    elem)) != NULL) {
1289					nvlist_add_string(tmpnvl,
1290					    nvpair_name(elem), zc->zc_string);
1291				}
1292			}
1293			nvlist_free(hnvl);
1294		} else {
1295			snapname = kmem_asprintf("%s@%s", zc->zc_name,
1296			    zc->zc_value);
1297			nvlist_add_string(tmpnvl, snapname, zc->zc_string);
1298			kmem_free(snapname, strlen(snapname + 1));
1299		}
1300		fnvlist_add_nvlist(nvl, "holds", tmpnvl);
1301		nvlist_free(tmpnvl);
1302		if (innvl != NULL)
1303			nvlist_free(innvl);
1304		/* strip dataset part from zc->zc_name */
1305		zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
1306		return (nvl);
1307	break;
1308	case ZFS_IOC_RELEASE:
1309		nvl = fnvlist_alloc();
1310		tmpnvl = fnvlist_alloc();
1311		if (zc->zc_cookie) {
1312			hnvl = fnvlist_alloc();
1313			if (dmu_get_recursive_snaps_nvl(zc->zc_name,
1314			    zc->zc_value, hnvl) == 0) {
1315				elem = NULL;
1316				while ((elem = nvlist_next_nvpair(hnvl,
1317				    elem)) != NULL) {
1318					fnvlist_add_boolean(tmpnvl,
1319					    zc->zc_string);
1320					fnvlist_add_nvlist(nvl,
1321					    nvpair_name(elem), tmpnvl);
1322				}
1323			}
1324			nvlist_free(hnvl);
1325		} else {
1326			snapname = kmem_asprintf("%s@%s", zc->zc_name,
1327			    zc->zc_value);
1328			fnvlist_add_boolean(tmpnvl, zc->zc_string);
1329			fnvlist_add_nvlist(nvl, snapname, tmpnvl);
1330			kmem_free(snapname, strlen(snapname + 1));
1331		}
1332		nvlist_free(tmpnvl);
1333		if (innvl != NULL)
1334			nvlist_free(innvl);
1335		/* strip dataset part from zc->zc_name */
1336		zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
1337		return (nvl);
1338	break;
1339	}
1340out:
1341	return (innvl);
1342}
1343
1344nvlist_t *
1345zfs_ioctl_compat_outnvl(zfs_cmd_t *zc, nvlist_t * outnvl, const int vec,
1346    const int cflag)
1347{
1348	nvlist_t *tmpnvl;
1349
1350	if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC ||
1351	    cflag == ZFS_CMD_COMPAT_ZCMD || cflag == ZFS_CMD_COMPAT_EDBP ||
1352	    cflag == ZFS_CMD_COMPAT_RESUME || cflag == ZFS_CMD_COMPAT_INLANES)
1353		return (outnvl);
1354
1355	switch (vec) {
1356	case ZFS_IOC_SPACE_SNAPS:
1357		(void) nvlist_lookup_uint64(outnvl, "used", &zc->zc_cookie);
1358		(void) nvlist_lookup_uint64(outnvl, "compressed",
1359		    &zc->zc_objset_type);
1360		(void) nvlist_lookup_uint64(outnvl, "uncompressed",
1361		    &zc->zc_perm_action);
1362		nvlist_free(outnvl);
1363		/* return empty outnvl */
1364		tmpnvl = fnvlist_alloc();
1365		return (tmpnvl);
1366	break;
1367	case ZFS_IOC_CREATE:
1368	case ZFS_IOC_CLONE:
1369	case ZFS_IOC_HOLD:
1370	case ZFS_IOC_RELEASE:
1371		nvlist_free(outnvl);
1372		/* return empty outnvl */
1373		tmpnvl = fnvlist_alloc();
1374		return (tmpnvl);
1375	break;
1376	}
1377
1378	return (outnvl);
1379}
1380#endif /* KERNEL */
1381