xref: /netbsd-src/external/cddl/osnet/dist/common/zfs/zfs_ioctl_compat.c (revision 54ddcf50a8a5bf65e1896370f6551922cfa512d6)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2013 Xin Li <delphij@FreeBSD.org>. All rights reserved.
23  * Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
24  * Portions Copyright 2005, 2010, Oracle and/or its affiliates.
25  * All rights reserved.
26  * Use is subject to license terms.
27  */
28 
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/cred.h>
32 #include <sys/dmu.h>
33 #include <sys/zio.h>
34 #include <sys/nvpair.h>
35 #include <sys/dsl_deleg.h>
36 #include <sys/zfs_ioctl.h>
37 #include "zfs_namecheck.h"
38 #include "zfs_ioctl_compat.h"
39 
40 static int zfs_version_ioctl = ZFS_IOCVER_CURRENT;
41 SYSCTL_DECL(_vfs_zfs_version);
42 SYSCTL_INT(_vfs_zfs_version, OID_AUTO, ioctl, CTLFLAG_RD, &zfs_version_ioctl,
43     0, "ZFS_IOCTL_VERSION");
44 
45 /*
46  * FreeBSD zfs_cmd compatibility with older binaries
47  * appropriately remap/extend the zfs_cmd_t structure
48  */
49 void
zfs_cmd_compat_get(zfs_cmd_t * zc,caddr_t addr,const int cflag)50 zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_t addr, const int cflag)
51 {
52 	zfs_cmd_v15_t *zc_c;
53 	zfs_cmd_v28_t *zc28_c;
54 	zfs_cmd_deadman_t *zcdm_c;
55 	zfs_cmd_zcmd_t *zcmd_c;
56 	zfs_cmd_edbp_t *edbp_c;
57 	zfs_cmd_resume_t *resume_c;
58 	zfs_cmd_inlanes_t *inlanes_c;
59 
60 	switch (cflag) {
61 	case ZFS_CMD_COMPAT_INLANES:
62 		inlanes_c = (void *)addr;
63 		/* zc */
64 		strlcpy(zc->zc_name, inlanes_c->zc_name, MAXPATHLEN);
65 		strlcpy(zc->zc_value, inlanes_c->zc_value, MAXPATHLEN * 2);
66 		strlcpy(zc->zc_string, inlanes_c->zc_string, MAXPATHLEN);
67 
68 #define FIELD_COPY(field) zc->field = inlanes_c->field
69 		FIELD_COPY(zc_nvlist_src);
70 		FIELD_COPY(zc_nvlist_src_size);
71 		FIELD_COPY(zc_nvlist_dst);
72 		FIELD_COPY(zc_nvlist_dst_size);
73 		FIELD_COPY(zc_nvlist_dst_filled);
74 		FIELD_COPY(zc_pad2);
75 		FIELD_COPY(zc_history);
76 		FIELD_COPY(zc_guid);
77 		FIELD_COPY(zc_nvlist_conf);
78 		FIELD_COPY(zc_nvlist_conf_size);
79 		FIELD_COPY(zc_cookie);
80 		FIELD_COPY(zc_objset_type);
81 		FIELD_COPY(zc_perm_action);
82 		FIELD_COPY(zc_history_len);
83 		FIELD_COPY(zc_history_offset);
84 		FIELD_COPY(zc_obj);
85 		FIELD_COPY(zc_iflags);
86 		FIELD_COPY(zc_share);
87 		FIELD_COPY(zc_jailid);
88 		FIELD_COPY(zc_objset_stats);
89 		FIELD_COPY(zc_begin_record);
90 		FIELD_COPY(zc_inject_record);
91 		FIELD_COPY(zc_defer_destroy);
92 		FIELD_COPY(zc_flags);
93 		FIELD_COPY(zc_action_handle);
94 		FIELD_COPY(zc_cleanup_fd);
95 		FIELD_COPY(zc_simple);
96 		FIELD_COPY(zc_resumable);
97 		FIELD_COPY(zc_sendobj);
98 		FIELD_COPY(zc_fromobj);
99 		FIELD_COPY(zc_createtxg);
100 		FIELD_COPY(zc_stat);
101 #undef FIELD_COPY
102 		break;
103 
104 	case ZFS_CMD_COMPAT_RESUME:
105 		resume_c = (void *)addr;
106 		/* zc */
107 		strlcpy(zc->zc_name, resume_c->zc_name, MAXPATHLEN);
108 		strlcpy(zc->zc_value, resume_c->zc_value, MAXPATHLEN * 2);
109 		strlcpy(zc->zc_string, resume_c->zc_string, MAXPATHLEN);
110 
111 #define FIELD_COPY(field) zc->field = resume_c->field
112 		FIELD_COPY(zc_nvlist_src);
113 		FIELD_COPY(zc_nvlist_src_size);
114 		FIELD_COPY(zc_nvlist_dst);
115 		FIELD_COPY(zc_nvlist_dst_size);
116 		FIELD_COPY(zc_nvlist_dst_filled);
117 		FIELD_COPY(zc_pad2);
118 		FIELD_COPY(zc_history);
119 		FIELD_COPY(zc_guid);
120 		FIELD_COPY(zc_nvlist_conf);
121 		FIELD_COPY(zc_nvlist_conf_size);
122 		FIELD_COPY(zc_cookie);
123 		FIELD_COPY(zc_objset_type);
124 		FIELD_COPY(zc_perm_action);
125 		FIELD_COPY(zc_history_len);
126 		FIELD_COPY(zc_history_offset);
127 		FIELD_COPY(zc_obj);
128 		FIELD_COPY(zc_iflags);
129 		FIELD_COPY(zc_share);
130 		FIELD_COPY(zc_jailid);
131 		FIELD_COPY(zc_objset_stats);
132 		FIELD_COPY(zc_begin_record);
133 		FIELD_COPY(zc_inject_record.zi_objset);
134 		FIELD_COPY(zc_inject_record.zi_object);
135 		FIELD_COPY(zc_inject_record.zi_start);
136 		FIELD_COPY(zc_inject_record.zi_end);
137 		FIELD_COPY(zc_inject_record.zi_guid);
138 		FIELD_COPY(zc_inject_record.zi_level);
139 		FIELD_COPY(zc_inject_record.zi_error);
140 		FIELD_COPY(zc_inject_record.zi_type);
141 		FIELD_COPY(zc_inject_record.zi_freq);
142 		FIELD_COPY(zc_inject_record.zi_failfast);
143 		strlcpy(zc->zc_inject_record.zi_func,
144 		    resume_c->zc_inject_record.zi_func, MAXNAMELEN);
145 		FIELD_COPY(zc_inject_record.zi_iotype);
146 		FIELD_COPY(zc_inject_record.zi_duration);
147 		FIELD_COPY(zc_inject_record.zi_timer);
148 		zc->zc_inject_record.zi_nlanes = 1;
149 		FIELD_COPY(zc_inject_record.zi_cmd);
150 		FIELD_COPY(zc_inject_record.zi_pad);
151 		FIELD_COPY(zc_defer_destroy);
152 		FIELD_COPY(zc_flags);
153 		FIELD_COPY(zc_action_handle);
154 		FIELD_COPY(zc_cleanup_fd);
155 		FIELD_COPY(zc_simple);
156 		FIELD_COPY(zc_resumable);
157 		FIELD_COPY(zc_sendobj);
158 		FIELD_COPY(zc_fromobj);
159 		FIELD_COPY(zc_createtxg);
160 		FIELD_COPY(zc_stat);
161 #undef FIELD_COPY
162 		break;
163 
164 	case ZFS_CMD_COMPAT_EDBP:
165 		edbp_c = (void *)addr;
166 		/* zc */
167 		strlcpy(zc->zc_name, edbp_c->zc_name, MAXPATHLEN);
168 		strlcpy(zc->zc_value, edbp_c->zc_value, MAXPATHLEN * 2);
169 		strlcpy(zc->zc_string, edbp_c->zc_string, MAXPATHLEN);
170 
171 #define FIELD_COPY(field) zc->field = edbp_c->field
172 		FIELD_COPY(zc_nvlist_src);
173 		FIELD_COPY(zc_nvlist_src_size);
174 		FIELD_COPY(zc_nvlist_dst);
175 		FIELD_COPY(zc_nvlist_dst_size);
176 		FIELD_COPY(zc_nvlist_dst_filled);
177 		FIELD_COPY(zc_pad2);
178 		FIELD_COPY(zc_history);
179 		FIELD_COPY(zc_guid);
180 		FIELD_COPY(zc_nvlist_conf);
181 		FIELD_COPY(zc_nvlist_conf_size);
182 		FIELD_COPY(zc_cookie);
183 		FIELD_COPY(zc_objset_type);
184 		FIELD_COPY(zc_perm_action);
185 		FIELD_COPY(zc_history_len);
186 		FIELD_COPY(zc_history_offset);
187 		FIELD_COPY(zc_obj);
188 		FIELD_COPY(zc_iflags);
189 		FIELD_COPY(zc_share);
190 		FIELD_COPY(zc_jailid);
191 		FIELD_COPY(zc_objset_stats);
192 		zc->zc_begin_record.drr_u.drr_begin = edbp_c->zc_begin_record;
193 		FIELD_COPY(zc_inject_record.zi_objset);
194 		FIELD_COPY(zc_inject_record.zi_object);
195 		FIELD_COPY(zc_inject_record.zi_start);
196 		FIELD_COPY(zc_inject_record.zi_end);
197 		FIELD_COPY(zc_inject_record.zi_guid);
198 		FIELD_COPY(zc_inject_record.zi_level);
199 		FIELD_COPY(zc_inject_record.zi_error);
200 		FIELD_COPY(zc_inject_record.zi_type);
201 		FIELD_COPY(zc_inject_record.zi_freq);
202 		FIELD_COPY(zc_inject_record.zi_failfast);
203 		strlcpy(zc->zc_inject_record.zi_func,
204 		    edbp_c->zc_inject_record.zi_func, MAXNAMELEN);
205 		FIELD_COPY(zc_inject_record.zi_iotype);
206 		FIELD_COPY(zc_inject_record.zi_duration);
207 		FIELD_COPY(zc_inject_record.zi_timer);
208 		zc->zc_inject_record.zi_nlanes = 1;
209 		FIELD_COPY(zc_inject_record.zi_cmd);
210 		FIELD_COPY(zc_inject_record.zi_pad);
211 		FIELD_COPY(zc_defer_destroy);
212 		FIELD_COPY(zc_flags);
213 		FIELD_COPY(zc_action_handle);
214 		FIELD_COPY(zc_cleanup_fd);
215 		FIELD_COPY(zc_simple);
216 		zc->zc_resumable = B_FALSE;
217 		FIELD_COPY(zc_sendobj);
218 		FIELD_COPY(zc_fromobj);
219 		FIELD_COPY(zc_createtxg);
220 		FIELD_COPY(zc_stat);
221 #undef FIELD_COPY
222 		break;
223 
224 	case ZFS_CMD_COMPAT_ZCMD:
225 		zcmd_c = (void *)addr;
226 		/* zc */
227 		strlcpy(zc->zc_name, zcmd_c->zc_name, MAXPATHLEN);
228 		strlcpy(zc->zc_value, zcmd_c->zc_value, MAXPATHLEN * 2);
229 		strlcpy(zc->zc_string, zcmd_c->zc_string, MAXPATHLEN);
230 
231 #define FIELD_COPY(field) zc->field = zcmd_c->field
232 		FIELD_COPY(zc_nvlist_src);
233 		FIELD_COPY(zc_nvlist_src_size);
234 		FIELD_COPY(zc_nvlist_dst);
235 		FIELD_COPY(zc_nvlist_dst_size);
236 		FIELD_COPY(zc_nvlist_dst_filled);
237 		FIELD_COPY(zc_pad2);
238 		FIELD_COPY(zc_history);
239 		FIELD_COPY(zc_guid);
240 		FIELD_COPY(zc_nvlist_conf);
241 		FIELD_COPY(zc_nvlist_conf_size);
242 		FIELD_COPY(zc_cookie);
243 		FIELD_COPY(zc_objset_type);
244 		FIELD_COPY(zc_perm_action);
245 		FIELD_COPY(zc_history_len);
246 		FIELD_COPY(zc_history_offset);
247 		FIELD_COPY(zc_obj);
248 		FIELD_COPY(zc_iflags);
249 		FIELD_COPY(zc_share);
250 		FIELD_COPY(zc_jailid);
251 		FIELD_COPY(zc_objset_stats);
252 		zc->zc_begin_record.drr_u.drr_begin = zcmd_c->zc_begin_record;
253 		FIELD_COPY(zc_inject_record.zi_objset);
254 		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 		    zcdm_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 
471 void
zfs_cmd_compat_put(zfs_cmd_t * zc,caddr_t addr,const int request,const int cflag)472 zfs_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(edbp_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(zcmd_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(zcdm_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 
886 static int
zfs_ioctl_compat_get_nvlist(uint64_t nvl,size_t size,int iflag,nvlist_t ** nvp)887 zfs_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 
924 static int
zfs_ioctl_compat_put_nvlist(zfs_cmd_t * zc,nvlist_t * nvl)925 zfs_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 
952 static void
zfs_ioctl_compat_fix_stats_nvlist(nvlist_t * nvl)953 zfs_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 
993 static int
zfs_ioctl_compat_fix_stats(zfs_cmd_t * zc,const int nc)994 zfs_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 
1021 static int
zfs_ioctl_compat_pool_get_props(zfs_cmd_t * zc)1022 zfs_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
1061 int
zcmd_ioctl_compat(int fd,int request,zfs_cmd_t * zc,const int cflag)1062 zcmd_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 */
1150 int
zfs_ioctl_compat_pre(zfs_cmd_t * zc,int * vec,const int cflag)1151 zfs_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 
1171 void
zfs_ioctl_compat_post(zfs_cmd_t * zc,int vec,const int cflag)1172 zfs_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 
1188 nvlist_t *
zfs_ioctl_compat_innvl(zfs_cmd_t * zc,nvlist_t * innvl,const int vec,const int cflag)1189 zfs_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 	}
1340 out:
1341 	return (innvl);
1342 }
1343 
1344 nvlist_t *
zfs_ioctl_compat_outnvl(zfs_cmd_t * zc,nvlist_t * outnvl,const int vec,const int cflag)1345 zfs_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