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.
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.
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]
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.
29 #include <sys/types.h>
30 #include <sys/param.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"
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");
46 * FreeBSD zfs_cmd compatibility with older binaries
47 * appropriately remap/extend the zfs_cmd_t structure
50 zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_t addr, const int cflag)
53 zfs_cmd_v28_t *zc28_c;
54 zfs_cmd_deadman_t *zcdm_c;
55 zfs_cmd_zcmd_t *zcmd_c;
58 case ZFS_CMD_COMPAT_ZCMD:
59 zcmd_c = (void *)addr;
61 strlcpy(zc->zc_name, zcmd_c->zc_name, MAXPATHLEN);
62 strlcpy(zc->zc_value, zcmd_c->zc_value, MAXPATHLEN * 2);
63 strlcpy(zc->zc_string, zcmd_c->zc_string, MAXPATHLEN);
65 #define ZCMD_COPY(field) zc->field = zcmd_c->field
66 ZCMD_COPY(zc_nvlist_src);
67 ZCMD_COPY(zc_nvlist_src_size);
68 ZCMD_COPY(zc_nvlist_dst);
69 ZCMD_COPY(zc_nvlist_dst_size);
70 ZCMD_COPY(zc_nvlist_dst_filled);
72 ZCMD_COPY(zc_history);
74 ZCMD_COPY(zc_nvlist_conf);
75 ZCMD_COPY(zc_nvlist_conf_size);
77 ZCMD_COPY(zc_objset_type);
78 ZCMD_COPY(zc_perm_action);
79 ZCMD_COPY(zc_history_len);
80 ZCMD_COPY(zc_history_offset);
85 ZCMD_COPY(zc_objset_stats);
88 * zc_begin_record, zc_inject_record didn't change in embedeed-data
93 ZCMD_COPY(zc_begin_record);
94 ZCMD_COPY(zc_inject_record);
96 /* boolean_t -> uint32_t */
97 zc->zc_defer_destroy = (uint32_t)(zcmd_c->zc_defer_destroy);
100 ZCMD_COPY(zc_action_handle);
101 ZCMD_COPY(zc_cleanup_fd);
102 ZCMD_COPY(zc_simple);
103 bcopy(zcmd_c->zc_pad, zc->zc_pad, sizeof(zc->zc_pad));
104 ZCMD_COPY(zc_sendobj);
105 ZCMD_COPY(zc_fromobj);
106 ZCMD_COPY(zc_createtxg);
112 case ZFS_CMD_COMPAT_DEADMAN:
113 zcdm_c = (void *)addr;
115 strlcpy(zc->zc_name, zcdm_c->zc_name, MAXPATHLEN);
116 strlcpy(zc->zc_value, zcdm_c->zc_value, MAXPATHLEN * 2);
117 strlcpy(zc->zc_string, zcdm_c->zc_string, MAXPATHLEN);
118 zc->zc_guid = zcdm_c->zc_guid;
119 zc->zc_nvlist_conf = zcdm_c->zc_nvlist_conf;
120 zc->zc_nvlist_conf_size = zcdm_c->zc_nvlist_conf_size;
121 zc->zc_nvlist_src = zcdm_c->zc_nvlist_src;
122 zc->zc_nvlist_src_size = zcdm_c->zc_nvlist_src_size;
123 zc->zc_nvlist_dst = zcdm_c->zc_nvlist_dst;
124 zc->zc_nvlist_dst_size = zcdm_c->zc_nvlist_dst_size;
125 zc->zc_cookie = zcdm_c->zc_cookie;
126 zc->zc_objset_type = zcdm_c->zc_objset_type;
127 zc->zc_perm_action = zcdm_c->zc_perm_action;
128 zc->zc_history = zcdm_c->zc_history;
129 zc->zc_history_len = zcdm_c->zc_history_len;
130 zc->zc_history_offset = zcdm_c->zc_history_offset;
131 zc->zc_obj = zcdm_c->zc_obj;
132 zc->zc_iflags = zcdm_c->zc_iflags;
133 zc->zc_share = zcdm_c->zc_share;
134 zc->zc_jailid = zcdm_c->zc_jailid;
135 zc->zc_objset_stats = zcdm_c->zc_objset_stats;
136 zc->zc_begin_record = zcdm_c->zc_begin_record;
137 zc->zc_defer_destroy = zcdm_c->zc_defer_destroy;
138 (void)zcdm_c->zc_temphold;
139 zc->zc_action_handle = zcdm_c->zc_action_handle;
140 zc->zc_cleanup_fd = zcdm_c->zc_cleanup_fd;
141 zc->zc_simple = zcdm_c->zc_simple;
142 bcopy(zcdm_c->zc_pad, zc->zc_pad, sizeof(zc->zc_pad));
143 zc->zc_sendobj = zcdm_c->zc_sendobj;
144 zc->zc_fromobj = zcdm_c->zc_fromobj;
145 zc->zc_createtxg = zcdm_c->zc_createtxg;
146 zc->zc_stat = zcdm_c->zc_stat;
148 /* zc_inject_record doesn't change in libzfs_core */
149 zcdm_c->zc_inject_record = zc->zc_inject_record;
151 /* we always assume zc_nvlist_dst_filled is true */
152 zc->zc_nvlist_dst_filled = B_TRUE;
155 case ZFS_CMD_COMPAT_V28:
156 zc28_c = (void *)addr;
159 strlcpy(zc->zc_name, zc28_c->zc_name, MAXPATHLEN);
160 strlcpy(zc->zc_value, zc28_c->zc_value, MAXPATHLEN * 2);
161 strlcpy(zc->zc_string, zc28_c->zc_string, MAXPATHLEN);
162 zc->zc_guid = zc28_c->zc_guid;
163 zc->zc_nvlist_conf = zc28_c->zc_nvlist_conf;
164 zc->zc_nvlist_conf_size = zc28_c->zc_nvlist_conf_size;
165 zc->zc_nvlist_src = zc28_c->zc_nvlist_src;
166 zc->zc_nvlist_src_size = zc28_c->zc_nvlist_src_size;
167 zc->zc_nvlist_dst = zc28_c->zc_nvlist_dst;
168 zc->zc_nvlist_dst_size = zc28_c->zc_nvlist_dst_size;
169 zc->zc_cookie = zc28_c->zc_cookie;
170 zc->zc_objset_type = zc28_c->zc_objset_type;
171 zc->zc_perm_action = zc28_c->zc_perm_action;
172 zc->zc_history = zc28_c->zc_history;
173 zc->zc_history_len = zc28_c->zc_history_len;
174 zc->zc_history_offset = zc28_c->zc_history_offset;
175 zc->zc_obj = zc28_c->zc_obj;
176 zc->zc_iflags = zc28_c->zc_iflags;
177 zc->zc_share = zc28_c->zc_share;
178 zc->zc_jailid = zc28_c->zc_jailid;
179 zc->zc_objset_stats = zc28_c->zc_objset_stats;
180 zc->zc_begin_record = zc28_c->zc_begin_record;
181 zc->zc_defer_destroy = zc28_c->zc_defer_destroy;
182 (void)zc28_c->zc_temphold;
183 zc->zc_action_handle = zc28_c->zc_action_handle;
184 zc->zc_cleanup_fd = zc28_c->zc_cleanup_fd;
185 zc->zc_simple = zc28_c->zc_simple;
186 bcopy(zc28_c->zc_pad, zc->zc_pad, sizeof(zc->zc_pad));
187 zc->zc_sendobj = zc28_c->zc_sendobj;
188 zc->zc_fromobj = zc28_c->zc_fromobj;
189 zc->zc_createtxg = zc28_c->zc_createtxg;
190 zc->zc_stat = zc28_c->zc_stat;
192 /* zc->zc_inject_record */
193 zc->zc_inject_record.zi_objset =
194 zc28_c->zc_inject_record.zi_objset;
195 zc->zc_inject_record.zi_object =
196 zc28_c->zc_inject_record.zi_object;
197 zc->zc_inject_record.zi_start =
198 zc28_c->zc_inject_record.zi_start;
199 zc->zc_inject_record.zi_end =
200 zc28_c->zc_inject_record.zi_end;
201 zc->zc_inject_record.zi_guid =
202 zc28_c->zc_inject_record.zi_guid;
203 zc->zc_inject_record.zi_level =
204 zc28_c->zc_inject_record.zi_level;
205 zc->zc_inject_record.zi_error =
206 zc28_c->zc_inject_record.zi_error;
207 zc->zc_inject_record.zi_type =
208 zc28_c->zc_inject_record.zi_type;
209 zc->zc_inject_record.zi_freq =
210 zc28_c->zc_inject_record.zi_freq;
211 zc->zc_inject_record.zi_failfast =
212 zc28_c->zc_inject_record.zi_failfast;
213 strlcpy(zc->zc_inject_record.zi_func,
214 zc28_c->zc_inject_record.zi_func, MAXNAMELEN);
215 zc->zc_inject_record.zi_iotype =
216 zc28_c->zc_inject_record.zi_iotype;
217 zc->zc_inject_record.zi_duration =
218 zc28_c->zc_inject_record.zi_duration;
219 zc->zc_inject_record.zi_timer =
220 zc28_c->zc_inject_record.zi_timer;
221 zc->zc_inject_record.zi_cmd = ZINJECT_UNINITIALIZED;
222 zc->zc_inject_record.zi_pad = 0;
225 case ZFS_CMD_COMPAT_V15:
229 strlcpy(zc->zc_name, zc_c->zc_name, MAXPATHLEN);
230 strlcpy(zc->zc_value, zc_c->zc_value, MAXPATHLEN);
231 strlcpy(zc->zc_string, zc_c->zc_string, MAXPATHLEN);
232 zc->zc_guid = zc_c->zc_guid;
233 zc->zc_nvlist_conf = zc_c->zc_nvlist_conf;
234 zc->zc_nvlist_conf_size = zc_c->zc_nvlist_conf_size;
235 zc->zc_nvlist_src = zc_c->zc_nvlist_src;
236 zc->zc_nvlist_src_size = zc_c->zc_nvlist_src_size;
237 zc->zc_nvlist_dst = zc_c->zc_nvlist_dst;
238 zc->zc_nvlist_dst_size = zc_c->zc_nvlist_dst_size;
239 zc->zc_cookie = zc_c->zc_cookie;
240 zc->zc_objset_type = zc_c->zc_objset_type;
241 zc->zc_perm_action = zc_c->zc_perm_action;
242 zc->zc_history = zc_c->zc_history;
243 zc->zc_history_len = zc_c->zc_history_len;
244 zc->zc_history_offset = zc_c->zc_history_offset;
245 zc->zc_obj = zc_c->zc_obj;
246 zc->zc_share = zc_c->zc_share;
247 zc->zc_jailid = zc_c->zc_jailid;
248 zc->zc_objset_stats = zc_c->zc_objset_stats;
249 zc->zc_begin_record = zc_c->zc_begin_record;
251 /* zc->zc_inject_record */
252 zc->zc_inject_record.zi_objset =
253 zc_c->zc_inject_record.zi_objset;
254 zc->zc_inject_record.zi_object =
255 zc_c->zc_inject_record.zi_object;
256 zc->zc_inject_record.zi_start =
257 zc_c->zc_inject_record.zi_start;
258 zc->zc_inject_record.zi_end =
259 zc_c->zc_inject_record.zi_end;
260 zc->zc_inject_record.zi_guid =
261 zc_c->zc_inject_record.zi_guid;
262 zc->zc_inject_record.zi_level =
263 zc_c->zc_inject_record.zi_level;
264 zc->zc_inject_record.zi_error =
265 zc_c->zc_inject_record.zi_error;
266 zc->zc_inject_record.zi_type =
267 zc_c->zc_inject_record.zi_type;
268 zc->zc_inject_record.zi_freq =
269 zc_c->zc_inject_record.zi_freq;
270 zc->zc_inject_record.zi_failfast =
271 zc_c->zc_inject_record.zi_failfast;
277 zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_t addr, const int request,
281 zfs_cmd_v28_t *zc28_c;
282 zfs_cmd_deadman_t *zcdm_c;
283 zfs_cmd_zcmd_t *zcmd_c;
286 case ZFS_CMD_COMPAT_ZCMD:
287 zcmd_c = (void *)addr;
289 strlcpy(zcmd_c->zc_name, zc->zc_name, MAXPATHLEN);
290 strlcpy(zcmd_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
291 strlcpy(zcmd_c->zc_string, zc->zc_string, MAXPATHLEN);
293 #define ZCMD_COPY(field) zcmd_c->field = zc->field
294 ZCMD_COPY(zc_nvlist_src);
295 ZCMD_COPY(zc_nvlist_src_size);
296 ZCMD_COPY(zc_nvlist_dst);
297 ZCMD_COPY(zc_nvlist_dst_size);
298 ZCMD_COPY(zc_nvlist_dst_filled);
300 ZCMD_COPY(zc_history);
302 ZCMD_COPY(zc_nvlist_conf);
303 ZCMD_COPY(zc_nvlist_conf_size);
304 ZCMD_COPY(zc_cookie);
305 ZCMD_COPY(zc_objset_type);
306 ZCMD_COPY(zc_perm_action);
307 ZCMD_COPY(zc_history_len);
308 ZCMD_COPY(zc_history_offset);
310 ZCMD_COPY(zc_iflags);
312 ZCMD_COPY(zc_jailid);
313 ZCMD_COPY(zc_objset_stats);
316 * zc_begin_record, zc_inject_record didn't change in embedeed-data
321 ZCMD_COPY(zc_begin_record);
322 ZCMD_COPY(zc_inject_record);
324 /* boolean_t -> uint32_t */
325 zcmd_c->zc_defer_destroy = (uint32_t)(zc->zc_defer_destroy);
326 zcmd_c->zc_temphold = 0;
328 ZCMD_COPY(zc_action_handle);
329 ZCMD_COPY(zc_cleanup_fd);
330 ZCMD_COPY(zc_simple);
331 bcopy(zc->zc_pad, zcmd_c->zc_pad, sizeof(zcmd_c->zc_pad));
332 ZCMD_COPY(zc_sendobj);
333 ZCMD_COPY(zc_fromobj);
334 ZCMD_COPY(zc_createtxg);
340 case ZFS_CMD_COMPAT_DEADMAN:
341 zcdm_c = (void *)addr;
343 strlcpy(zcdm_c->zc_name, zc->zc_name, MAXPATHLEN);
344 strlcpy(zcdm_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
345 strlcpy(zcdm_c->zc_string, zc->zc_string, MAXPATHLEN);
346 zcdm_c->zc_guid = zc->zc_guid;
347 zcdm_c->zc_nvlist_conf = zc->zc_nvlist_conf;
348 zcdm_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
349 zcdm_c->zc_nvlist_src = zc->zc_nvlist_src;
350 zcdm_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
351 zcdm_c->zc_nvlist_dst = zc->zc_nvlist_dst;
352 zcdm_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
353 zcdm_c->zc_cookie = zc->zc_cookie;
354 zcdm_c->zc_objset_type = zc->zc_objset_type;
355 zcdm_c->zc_perm_action = zc->zc_perm_action;
356 zcdm_c->zc_history = zc->zc_history;
357 zcdm_c->zc_history_len = zc->zc_history_len;
358 zcdm_c->zc_history_offset = zc->zc_history_offset;
359 zcdm_c->zc_obj = zc->zc_obj;
360 zcdm_c->zc_iflags = zc->zc_iflags;
361 zcdm_c->zc_share = zc->zc_share;
362 zcdm_c->zc_jailid = zc->zc_jailid;
363 zcdm_c->zc_objset_stats = zc->zc_objset_stats;
364 zcdm_c->zc_begin_record = zc->zc_begin_record;
365 zcdm_c->zc_defer_destroy = zc->zc_defer_destroy;
366 zcdm_c->zc_temphold = 0;
367 zcdm_c->zc_action_handle = zc->zc_action_handle;
368 zcdm_c->zc_cleanup_fd = zc->zc_cleanup_fd;
369 zcdm_c->zc_simple = zc->zc_simple;
370 bcopy(zc->zc_pad, zcdm_c->zc_pad, sizeof(zcdm_c->zc_pad));
371 zcdm_c->zc_sendobj = zc->zc_sendobj;
372 zcdm_c->zc_fromobj = zc->zc_fromobj;
373 zcdm_c->zc_createtxg = zc->zc_createtxg;
374 zcdm_c->zc_stat = zc->zc_stat;
376 /* zc_inject_record doesn't change in libzfs_core */
377 zc->zc_inject_record = zcdm_c->zc_inject_record;
379 if (request == ZFS_IOC_RECV)
380 strlcpy(zcdm_c->zc_top_ds,
381 zc->zc_value + strlen(zc->zc_value) + 1,
382 (MAXPATHLEN * 2) - strlen(zc->zc_value) - 1);
386 case ZFS_CMD_COMPAT_V28:
387 zc28_c = (void *)addr;
389 strlcpy(zc28_c->zc_name, zc->zc_name, MAXPATHLEN);
390 strlcpy(zc28_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
391 strlcpy(zc28_c->zc_string, zc->zc_string, MAXPATHLEN);
392 zc28_c->zc_guid = zc->zc_guid;
393 zc28_c->zc_nvlist_conf = zc->zc_nvlist_conf;
394 zc28_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
395 zc28_c->zc_nvlist_src = zc->zc_nvlist_src;
396 zc28_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
397 zc28_c->zc_nvlist_dst = zc->zc_nvlist_dst;
398 zc28_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
399 zc28_c->zc_cookie = zc->zc_cookie;
400 zc28_c->zc_objset_type = zc->zc_objset_type;
401 zc28_c->zc_perm_action = zc->zc_perm_action;
402 zc28_c->zc_history = zc->zc_history;
403 zc28_c->zc_history_len = zc->zc_history_len;
404 zc28_c->zc_history_offset = zc->zc_history_offset;
405 zc28_c->zc_obj = zc->zc_obj;
406 zc28_c->zc_iflags = zc->zc_iflags;
407 zc28_c->zc_share = zc->zc_share;
408 zc28_c->zc_jailid = zc->zc_jailid;
409 zc28_c->zc_objset_stats = zc->zc_objset_stats;
410 zc28_c->zc_begin_record = zc->zc_begin_record;
411 zc28_c->zc_defer_destroy = zc->zc_defer_destroy;
412 zc28_c->zc_temphold = 0;
413 zc28_c->zc_action_handle = zc->zc_action_handle;
414 zc28_c->zc_cleanup_fd = zc->zc_cleanup_fd;
415 zc28_c->zc_simple = zc->zc_simple;
416 bcopy(zc->zc_pad, zc28_c->zc_pad, sizeof(zc28_c->zc_pad));
417 zc28_c->zc_sendobj = zc->zc_sendobj;
418 zc28_c->zc_fromobj = zc->zc_fromobj;
419 zc28_c->zc_createtxg = zc->zc_createtxg;
420 zc28_c->zc_stat = zc->zc_stat;
422 if (request == ZFS_IOC_RECV)
423 strlcpy(zc28_c->zc_top_ds,
424 zc->zc_value + strlen(zc->zc_value) + 1,
425 MAXPATHLEN * 2 - strlen(zc->zc_value) - 1);
427 /* zc_inject_record */
428 zc28_c->zc_inject_record.zi_objset =
429 zc->zc_inject_record.zi_objset;
430 zc28_c->zc_inject_record.zi_object =
431 zc->zc_inject_record.zi_object;
432 zc28_c->zc_inject_record.zi_start =
433 zc->zc_inject_record.zi_start;
434 zc28_c->zc_inject_record.zi_end =
435 zc->zc_inject_record.zi_end;
436 zc28_c->zc_inject_record.zi_guid =
437 zc->zc_inject_record.zi_guid;
438 zc28_c->zc_inject_record.zi_level =
439 zc->zc_inject_record.zi_level;
440 zc28_c->zc_inject_record.zi_error =
441 zc->zc_inject_record.zi_error;
442 zc28_c->zc_inject_record.zi_type =
443 zc->zc_inject_record.zi_type;
444 zc28_c->zc_inject_record.zi_freq =
445 zc->zc_inject_record.zi_freq;
446 zc28_c->zc_inject_record.zi_failfast =
447 zc->zc_inject_record.zi_failfast;
448 strlcpy(zc28_c->zc_inject_record.zi_func,
449 zc->zc_inject_record.zi_func, MAXNAMELEN);
450 zc28_c->zc_inject_record.zi_iotype =
451 zc->zc_inject_record.zi_iotype;
452 zc28_c->zc_inject_record.zi_duration =
453 zc->zc_inject_record.zi_duration;
454 zc28_c->zc_inject_record.zi_timer =
455 zc->zc_inject_record.zi_timer;
458 case ZFS_CMD_COMPAT_V15:
462 strlcpy(zc_c->zc_name, zc->zc_name, MAXPATHLEN);
463 strlcpy(zc_c->zc_value, zc->zc_value, MAXPATHLEN);
464 strlcpy(zc_c->zc_string, zc->zc_string, MAXPATHLEN);
465 zc_c->zc_guid = zc->zc_guid;
466 zc_c->zc_nvlist_conf = zc->zc_nvlist_conf;
467 zc_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
468 zc_c->zc_nvlist_src = zc->zc_nvlist_src;
469 zc_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
470 zc_c->zc_nvlist_dst = zc->zc_nvlist_dst;
471 zc_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
472 zc_c->zc_cookie = zc->zc_cookie;
473 zc_c->zc_objset_type = zc->zc_objset_type;
474 zc_c->zc_perm_action = zc->zc_perm_action;
475 zc_c->zc_history = zc->zc_history;
476 zc_c->zc_history_len = zc->zc_history_len;
477 zc_c->zc_history_offset = zc->zc_history_offset;
478 zc_c->zc_obj = zc->zc_obj;
479 zc_c->zc_share = zc->zc_share;
480 zc_c->zc_jailid = zc->zc_jailid;
481 zc_c->zc_objset_stats = zc->zc_objset_stats;
482 zc_c->zc_begin_record = zc->zc_begin_record;
484 /* zc_inject_record */
485 zc_c->zc_inject_record.zi_objset =
486 zc->zc_inject_record.zi_objset;
487 zc_c->zc_inject_record.zi_object =
488 zc->zc_inject_record.zi_object;
489 zc_c->zc_inject_record.zi_start =
490 zc->zc_inject_record.zi_start;
491 zc_c->zc_inject_record.zi_end =
492 zc->zc_inject_record.zi_end;
493 zc_c->zc_inject_record.zi_guid =
494 zc->zc_inject_record.zi_guid;
495 zc_c->zc_inject_record.zi_level =
496 zc->zc_inject_record.zi_level;
497 zc_c->zc_inject_record.zi_error =
498 zc->zc_inject_record.zi_error;
499 zc_c->zc_inject_record.zi_type =
500 zc->zc_inject_record.zi_type;
501 zc_c->zc_inject_record.zi_freq =
502 zc->zc_inject_record.zi_freq;
503 zc_c->zc_inject_record.zi_failfast =
504 zc->zc_inject_record.zi_failfast;
511 zfs_ioctl_compat_get_nvlist(uint64_t nvl, size_t size, int iflag,
516 nvlist_t *list = NULL;
519 * Read in and unpack the user-supplied nvlist.
525 packed = kmem_alloc(size, KM_SLEEP);
526 if ((error = ddi_copyin((void *)(uintptr_t)nvl, packed, size,
528 kmem_free(packed, size);
532 packed = (void *)(uintptr_t)nvl;
535 error = nvlist_unpack(packed, size, &list, 0);
538 kmem_free(packed, size);
549 zfs_ioctl_compat_put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
555 VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0);
558 packed = kmem_alloc(size, KM_SLEEP);
559 VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
562 if (ddi_copyout(packed,
563 (void *)(uintptr_t)zc->zc_nvlist_dst, size, zc->zc_iflags) != 0)
565 kmem_free(packed, size);
567 packed = (void *)(uintptr_t)zc->zc_nvlist_dst;
568 VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
572 zc->zc_nvlist_dst_size = size;
577 zfs_ioctl_compat_fix_stats_nvlist(nvlist_t *nvl)
580 nvlist_t *nvroot = NULL;
582 uint_t c, children, nelem;
584 if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_CHILDREN,
585 &child, &children) == 0) {
586 for (c = 0; c < children; c++) {
587 zfs_ioctl_compat_fix_stats_nvlist(child[c]);
591 if (nvlist_lookup_nvlist(nvl, ZPOOL_CONFIG_VDEV_TREE,
593 zfs_ioctl_compat_fix_stats_nvlist(nvroot);
595 if ((nvlist_lookup_uint64_array(nvl, ZPOOL_CONFIG_VDEV_STATS,
597 if ((nvlist_lookup_uint64_array(nvl, "stats",
600 (uint64_t **)&vs, &nelem) == 0)) {
601 nvlist_add_uint64_array(nvl,
605 ZPOOL_CONFIG_VDEV_STATS,
607 (uint64_t *)vs, nelem);
609 nvlist_remove(nvl, ZPOOL_CONFIG_VDEV_STATS,
611 nvlist_remove(nvl, "stats",
613 DATA_TYPE_UINT64_ARRAY);
618 zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int nc)
620 nvlist_t *nv, *nvp = NULL;
624 if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst,
625 zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
628 if (nc == 5) { /* ZFS_IOC_POOL_STATS */
630 while ((elem = nvlist_next_nvpair(nv, elem)) != NULL) {
631 if (nvpair_value_nvlist(elem, &nvp) == 0)
632 zfs_ioctl_compat_fix_stats_nvlist(nvp);
636 zfs_ioctl_compat_fix_stats_nvlist(nv);
638 error = zfs_ioctl_compat_put_nvlist(zc, nv);
646 zfs_ioctl_compat_pool_get_props(zfs_cmd_t *zc)
648 nvlist_t *nv, *nva = NULL;
651 if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst,
652 zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
656 if (nvlist_lookup_nvlist(nv, "allocated", &nva) == 0) {
657 nvlist_add_nvlist(nv, "used", nva);
658 nvlist_remove(nv, "allocated", DATA_TYPE_NVLIST);
661 if (nvlist_lookup_nvlist(nv, "free", &nva) == 0) {
662 nvlist_add_nvlist(nv, "available", nva);
663 nvlist_remove(nv, "free", DATA_TYPE_NVLIST);
666 if (nvlist_lookup_nvlist(nv, "used", &nva) == 0) {
667 nvlist_add_nvlist(nv, "allocated", nva);
668 nvlist_remove(nv, "used", DATA_TYPE_NVLIST);
671 if (nvlist_lookup_nvlist(nv, "available", &nva) == 0) {
672 nvlist_add_nvlist(nv, "free", nva);
673 nvlist_remove(nv, "available", DATA_TYPE_NVLIST);
677 error = zfs_ioctl_compat_put_nvlist(zc, nv);
686 zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag)
694 case ZFS_CMD_COMPAT_NONE:
695 ncmd = _IOWR('Z', request, struct zfs_iocparm);
696 zp.zfs_cmd = (uint64_t)zc;
697 zp.zfs_cmd_size = sizeof(zfs_cmd_t);
698 zp.zfs_ioctl_version = ZFS_IOCVER_CURRENT;
699 return (ioctl(fd, ncmd, &zp));
700 case ZFS_CMD_COMPAT_LZC:
701 ncmd = _IOWR('Z', request, struct zfs_cmd);
702 return (ioctl(fd, ncmd, zc));
703 case ZFS_CMD_COMPAT_DEADMAN:
704 zc_c = malloc(sizeof(zfs_cmd_deadman_t));
705 ncmd = _IOWR('Z', request, struct zfs_cmd_deadman);
707 case ZFS_CMD_COMPAT_V28:
708 zc_c = malloc(sizeof(zfs_cmd_v28_t));
709 ncmd = _IOWR('Z', request, struct zfs_cmd_v28);
711 case ZFS_CMD_COMPAT_V15:
712 nc = zfs_ioctl_v28_to_v15[request];
713 zc_c = malloc(sizeof(zfs_cmd_v15_t));
714 ncmd = _IOWR('Z', nc, struct zfs_cmd_v15);
720 if (ZFS_IOCREQ(ncmd) == ZFS_IOC_COMPAT_FAIL)
723 zfs_cmd_compat_put(zc, (caddr_t)zc_c, request, cflag);
725 ret = ioctl(fd, ncmd, zc_c);
726 if (cflag == ZFS_CMD_COMPAT_V15 &&
727 nc == ZFS_IOC_POOL_IMPORT)
728 ret = ioctl(fd, _IOWR('Z', ZFS_IOC_POOL_CONFIGS,
729 struct zfs_cmd_v15), zc_c);
730 zfs_cmd_compat_get(zc, (caddr_t)zc_c, cflag);
733 if (cflag == ZFS_CMD_COMPAT_V15) {
735 case ZFS_IOC_POOL_IMPORT:
736 case ZFS_IOC_POOL_CONFIGS:
737 case ZFS_IOC_POOL_STATS:
738 case ZFS_IOC_POOL_TRYIMPORT:
739 zfs_ioctl_compat_fix_stats(zc, nc);
741 case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
742 zfs_ioctl_compat_pool_get_props(zc);
751 zfs_ioctl_compat_pre(zfs_cmd_t *zc, int *vec, const int cflag)
755 /* are we creating a clone? */
756 if (*vec == ZFS_IOC_CREATE && zc->zc_value[0] != '\0')
757 *vec = ZFS_IOC_CLONE;
759 if (cflag == ZFS_CMD_COMPAT_V15) {
762 case 7: /* ZFS_IOC_POOL_SCRUB (v15) */
763 zc->zc_cookie = POOL_SCAN_SCRUB;
772 zfs_ioctl_compat_post(zfs_cmd_t *zc, int vec, const int cflag)
774 if (cflag == ZFS_CMD_COMPAT_V15) {
776 case ZFS_IOC_POOL_CONFIGS:
777 case ZFS_IOC_POOL_STATS:
778 case ZFS_IOC_POOL_TRYIMPORT:
779 zfs_ioctl_compat_fix_stats(zc, vec);
781 case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
782 zfs_ioctl_compat_pool_get_props(zc);
789 zfs_ioctl_compat_innvl(zfs_cmd_t *zc, nvlist_t * innvl, const int vec,
792 nvlist_t *nvl, *tmpnvl, *hnvl;
794 char *poolname, *snapname;
797 if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC)
802 nvl = fnvlist_alloc();
803 fnvlist_add_int32(nvl, "type", zc->zc_objset_type);
805 fnvlist_add_nvlist(nvl, "props", innvl);
811 nvl = fnvlist_alloc();
812 fnvlist_add_string(nvl, "origin", zc->zc_value);
814 fnvlist_add_nvlist(nvl, "props", innvl);
819 case ZFS_IOC_SNAPSHOT:
822 nvl = fnvlist_alloc();
823 fnvlist_add_nvlist(nvl, "props", innvl);
824 tmpnvl = fnvlist_alloc();
825 snapname = kmem_asprintf("%s@%s", zc->zc_name, zc->zc_value);
826 fnvlist_add_boolean(tmpnvl, snapname);
827 kmem_free(snapname, strlen(snapname + 1));
828 /* check if we are doing a recursive snapshot */
830 dmu_get_recursive_snaps_nvl(zc->zc_name, zc->zc_value,
832 fnvlist_add_nvlist(nvl, "snaps", tmpnvl);
833 fnvlist_free(tmpnvl);
835 /* strip dataset part from zc->zc_name */
836 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
839 case ZFS_IOC_SPACE_SNAPS:
840 nvl = fnvlist_alloc();
841 fnvlist_add_string(nvl, "firstsnap", zc->zc_value);
846 case ZFS_IOC_DESTROY_SNAPS:
847 if (innvl == NULL && cflag == ZFS_CMD_COMPAT_DEADMAN)
849 nvl = fnvlist_alloc();
851 fnvlist_add_nvlist(nvl, "snaps", innvl);
854 * We are probably called by even older binaries,
855 * allocate and populate nvlist with recursive
858 if (zfs_component_namecheck(zc->zc_value, NULL,
860 tmpnvl = fnvlist_alloc();
861 if (dmu_get_recursive_snaps_nvl(zc->zc_name,
862 zc->zc_value, tmpnvl) == 0)
863 fnvlist_add_nvlist(nvl, "snaps",
870 /* strip dataset part from zc->zc_name */
871 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
875 nvl = fnvlist_alloc();
876 tmpnvl = fnvlist_alloc();
877 if (zc->zc_cleanup_fd != -1)
878 fnvlist_add_int32(nvl, "cleanup_fd",
879 (int32_t)zc->zc_cleanup_fd);
881 hnvl = fnvlist_alloc();
882 if (dmu_get_recursive_snaps_nvl(zc->zc_name,
883 zc->zc_value, hnvl) == 0) {
885 while ((elem = nvlist_next_nvpair(hnvl,
887 nvlist_add_string(tmpnvl,
888 nvpair_name(elem), zc->zc_string);
893 snapname = kmem_asprintf("%s@%s", zc->zc_name,
895 nvlist_add_string(tmpnvl, snapname, zc->zc_string);
896 kmem_free(snapname, strlen(snapname + 1));
898 fnvlist_add_nvlist(nvl, "holds", tmpnvl);
902 /* strip dataset part from zc->zc_name */
903 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
906 case ZFS_IOC_RELEASE:
907 nvl = fnvlist_alloc();
908 tmpnvl = fnvlist_alloc();
910 hnvl = fnvlist_alloc();
911 if (dmu_get_recursive_snaps_nvl(zc->zc_name,
912 zc->zc_value, hnvl) == 0) {
914 while ((elem = nvlist_next_nvpair(hnvl,
916 fnvlist_add_boolean(tmpnvl,
918 fnvlist_add_nvlist(nvl,
919 nvpair_name(elem), tmpnvl);
924 snapname = kmem_asprintf("%s@%s", zc->zc_name,
926 fnvlist_add_boolean(tmpnvl, zc->zc_string);
927 fnvlist_add_nvlist(nvl, snapname, tmpnvl);
928 kmem_free(snapname, strlen(snapname + 1));
933 /* strip dataset part from zc->zc_name */
934 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
943 zfs_ioctl_compat_outnvl(zfs_cmd_t *zc, nvlist_t * outnvl, const int vec,
948 if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC)
952 case ZFS_IOC_SPACE_SNAPS:
953 (void) nvlist_lookup_uint64(outnvl, "used", &zc->zc_cookie);
954 (void) nvlist_lookup_uint64(outnvl, "compressed",
955 &zc->zc_objset_type);
956 (void) nvlist_lookup_uint64(outnvl, "uncompressed",
957 &zc->zc_perm_action);
959 /* return empty outnvl */
960 tmpnvl = fnvlist_alloc();
966 case ZFS_IOC_RELEASE:
968 /* return empty outnvl */
969 tmpnvl = fnvlist_alloc();