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