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 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
23 * Portions Copyright 2005, 2010, Oracle and/or its affiliates.
24 * All rights reserved.
25 * Use is subject to license terms.
28 #include <sys/types.h>
29 #include <sys/param.h>
33 #include <sys/nvpair.h>
34 #include <sys/dsl_deleg.h>
35 #include <sys/zfs_ioctl.h>
36 #include "zfs_namecheck.h"
37 #include "zfs_ioctl_compat.h"
39 static int zfs_version_ioctl = ZFS_IOCVER_CURRENT;
40 SYSCTL_DECL(_vfs_zfs_version);
41 SYSCTL_INT(_vfs_zfs_version, OID_AUTO, ioctl, CTLFLAG_RD, &zfs_version_ioctl,
42 0, "ZFS_IOCTL_VERSION");
45 * FreeBSD zfs_cmd compatibility with older binaries
46 * appropriately remap/extend the zfs_cmd_t structure
49 zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_t addr, const int cflag)
52 zfs_cmd_v28_t *zc28_c;
53 zfs_cmd_deadman_t *zcdm_c;
56 case ZFS_CMD_COMPAT_DEADMAN:
57 zcdm_c = (void *)addr;
59 strlcpy(zc->zc_name, zcdm_c->zc_name, MAXPATHLEN);
60 strlcpy(zc->zc_value, zcdm_c->zc_value, MAXPATHLEN * 2);
61 strlcpy(zc->zc_string, zcdm_c->zc_string, MAXPATHLEN);
62 zc->zc_guid = zcdm_c->zc_guid;
63 zc->zc_nvlist_conf = zcdm_c->zc_nvlist_conf;
64 zc->zc_nvlist_conf_size = zcdm_c->zc_nvlist_conf_size;
65 zc->zc_nvlist_src = zcdm_c->zc_nvlist_src;
66 zc->zc_nvlist_src_size = zcdm_c->zc_nvlist_src_size;
67 zc->zc_nvlist_dst = zcdm_c->zc_nvlist_dst;
68 zc->zc_nvlist_dst_size = zcdm_c->zc_nvlist_dst_size;
69 zc->zc_cookie = zcdm_c->zc_cookie;
70 zc->zc_objset_type = zcdm_c->zc_objset_type;
71 zc->zc_perm_action = zcdm_c->zc_perm_action;
72 zc->zc_history = zcdm_c->zc_history;
73 zc->zc_history_len = zcdm_c->zc_history_len;
74 zc->zc_history_offset = zcdm_c->zc_history_offset;
75 zc->zc_obj = zcdm_c->zc_obj;
76 zc->zc_iflags = zcdm_c->zc_iflags;
77 zc->zc_share = zcdm_c->zc_share;
78 zc->zc_jailid = zcdm_c->zc_jailid;
79 zc->zc_objset_stats = zcdm_c->zc_objset_stats;
80 zc->zc_begin_record = zcdm_c->zc_begin_record;
81 zc->zc_defer_destroy = zcdm_c->zc_defer_destroy;
82 zc->zc_temphold = zcdm_c->zc_temphold;
83 zc->zc_action_handle = zcdm_c->zc_action_handle;
84 zc->zc_cleanup_fd = zcdm_c->zc_cleanup_fd;
85 zc->zc_simple = zcdm_c->zc_simple;
86 bcopy(zcdm_c->zc_pad, zc->zc_pad, sizeof(zc->zc_pad));
87 zc->zc_sendobj = zcdm_c->zc_sendobj;
88 zc->zc_fromobj = zcdm_c->zc_fromobj;
89 zc->zc_createtxg = zcdm_c->zc_createtxg;
90 zc->zc_stat = zcdm_c->zc_stat;
92 /* zc_inject_record doesn't change in libzfs_core */
93 zcdm_c->zc_inject_record = zc->zc_inject_record;
95 /* we always assume zc_nvlist_dst_filled is true */
96 zc->zc_nvlist_dst_filled = B_TRUE;
99 case ZFS_CMD_COMPAT_V28:
100 zc28_c = (void *)addr;
103 strlcpy(zc->zc_name, zc28_c->zc_name, MAXPATHLEN);
104 strlcpy(zc->zc_value, zc28_c->zc_value, MAXPATHLEN * 2);
105 strlcpy(zc->zc_string, zc28_c->zc_string, MAXPATHLEN);
106 zc->zc_guid = zc28_c->zc_guid;
107 zc->zc_nvlist_conf = zc28_c->zc_nvlist_conf;
108 zc->zc_nvlist_conf_size = zc28_c->zc_nvlist_conf_size;
109 zc->zc_nvlist_src = zc28_c->zc_nvlist_src;
110 zc->zc_nvlist_src_size = zc28_c->zc_nvlist_src_size;
111 zc->zc_nvlist_dst = zc28_c->zc_nvlist_dst;
112 zc->zc_nvlist_dst_size = zc28_c->zc_nvlist_dst_size;
113 zc->zc_cookie = zc28_c->zc_cookie;
114 zc->zc_objset_type = zc28_c->zc_objset_type;
115 zc->zc_perm_action = zc28_c->zc_perm_action;
116 zc->zc_history = zc28_c->zc_history;
117 zc->zc_history_len = zc28_c->zc_history_len;
118 zc->zc_history_offset = zc28_c->zc_history_offset;
119 zc->zc_obj = zc28_c->zc_obj;
120 zc->zc_iflags = zc28_c->zc_iflags;
121 zc->zc_share = zc28_c->zc_share;
122 zc->zc_jailid = zc28_c->zc_jailid;
123 zc->zc_objset_stats = zc28_c->zc_objset_stats;
124 zc->zc_begin_record = zc28_c->zc_begin_record;
125 zc->zc_defer_destroy = zc28_c->zc_defer_destroy;
126 zc->zc_temphold = zc28_c->zc_temphold;
127 zc->zc_action_handle = zc28_c->zc_action_handle;
128 zc->zc_cleanup_fd = zc28_c->zc_cleanup_fd;
129 zc->zc_simple = zc28_c->zc_simple;
130 bcopy(zc28_c->zc_pad, zc->zc_pad, sizeof(zc->zc_pad));
131 zc->zc_sendobj = zc28_c->zc_sendobj;
132 zc->zc_fromobj = zc28_c->zc_fromobj;
133 zc->zc_createtxg = zc28_c->zc_createtxg;
134 zc->zc_stat = zc28_c->zc_stat;
136 /* zc->zc_inject_record */
137 zc->zc_inject_record.zi_objset =
138 zc28_c->zc_inject_record.zi_objset;
139 zc->zc_inject_record.zi_object =
140 zc28_c->zc_inject_record.zi_object;
141 zc->zc_inject_record.zi_start =
142 zc28_c->zc_inject_record.zi_start;
143 zc->zc_inject_record.zi_end =
144 zc28_c->zc_inject_record.zi_end;
145 zc->zc_inject_record.zi_guid =
146 zc28_c->zc_inject_record.zi_guid;
147 zc->zc_inject_record.zi_level =
148 zc28_c->zc_inject_record.zi_level;
149 zc->zc_inject_record.zi_error =
150 zc28_c->zc_inject_record.zi_error;
151 zc->zc_inject_record.zi_type =
152 zc28_c->zc_inject_record.zi_type;
153 zc->zc_inject_record.zi_freq =
154 zc28_c->zc_inject_record.zi_freq;
155 zc->zc_inject_record.zi_failfast =
156 zc28_c->zc_inject_record.zi_failfast;
157 strlcpy(zc->zc_inject_record.zi_func,
158 zc28_c->zc_inject_record.zi_func, MAXNAMELEN);
159 zc->zc_inject_record.zi_iotype =
160 zc28_c->zc_inject_record.zi_iotype;
161 zc->zc_inject_record.zi_duration =
162 zc28_c->zc_inject_record.zi_duration;
163 zc->zc_inject_record.zi_timer =
164 zc28_c->zc_inject_record.zi_timer;
165 zc->zc_inject_record.zi_cmd = ZINJECT_UNINITIALIZED;
166 zc->zc_inject_record.zi_pad = 0;
169 case ZFS_CMD_COMPAT_V15:
173 strlcpy(zc->zc_name, zc_c->zc_name, MAXPATHLEN);
174 strlcpy(zc->zc_value, zc_c->zc_value, MAXPATHLEN);
175 strlcpy(zc->zc_string, zc_c->zc_string, MAXPATHLEN);
176 zc->zc_guid = zc_c->zc_guid;
177 zc->zc_nvlist_conf = zc_c->zc_nvlist_conf;
178 zc->zc_nvlist_conf_size = zc_c->zc_nvlist_conf_size;
179 zc->zc_nvlist_src = zc_c->zc_nvlist_src;
180 zc->zc_nvlist_src_size = zc_c->zc_nvlist_src_size;
181 zc->zc_nvlist_dst = zc_c->zc_nvlist_dst;
182 zc->zc_nvlist_dst_size = zc_c->zc_nvlist_dst_size;
183 zc->zc_cookie = zc_c->zc_cookie;
184 zc->zc_objset_type = zc_c->zc_objset_type;
185 zc->zc_perm_action = zc_c->zc_perm_action;
186 zc->zc_history = zc_c->zc_history;
187 zc->zc_history_len = zc_c->zc_history_len;
188 zc->zc_history_offset = zc_c->zc_history_offset;
189 zc->zc_obj = zc_c->zc_obj;
190 zc->zc_share = zc_c->zc_share;
191 zc->zc_jailid = zc_c->zc_jailid;
192 zc->zc_objset_stats = zc_c->zc_objset_stats;
193 zc->zc_begin_record = zc_c->zc_begin_record;
195 /* zc->zc_inject_record */
196 zc->zc_inject_record.zi_objset =
197 zc_c->zc_inject_record.zi_objset;
198 zc->zc_inject_record.zi_object =
199 zc_c->zc_inject_record.zi_object;
200 zc->zc_inject_record.zi_start =
201 zc_c->zc_inject_record.zi_start;
202 zc->zc_inject_record.zi_end =
203 zc_c->zc_inject_record.zi_end;
204 zc->zc_inject_record.zi_guid =
205 zc_c->zc_inject_record.zi_guid;
206 zc->zc_inject_record.zi_level =
207 zc_c->zc_inject_record.zi_level;
208 zc->zc_inject_record.zi_error =
209 zc_c->zc_inject_record.zi_error;
210 zc->zc_inject_record.zi_type =
211 zc_c->zc_inject_record.zi_type;
212 zc->zc_inject_record.zi_freq =
213 zc_c->zc_inject_record.zi_freq;
214 zc->zc_inject_record.zi_failfast =
215 zc_c->zc_inject_record.zi_failfast;
221 zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_t addr, const int request,
225 zfs_cmd_v28_t *zc28_c;
226 zfs_cmd_deadman_t *zcdm_c;
229 case ZFS_CMD_COMPAT_DEADMAN:
230 zcdm_c = (void *)addr;
232 strlcpy(zcdm_c->zc_name, zc->zc_name, MAXPATHLEN);
233 strlcpy(zcdm_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
234 strlcpy(zcdm_c->zc_string, zc->zc_string, MAXPATHLEN);
235 zcdm_c->zc_guid = zc->zc_guid;
236 zcdm_c->zc_nvlist_conf = zc->zc_nvlist_conf;
237 zcdm_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
238 zcdm_c->zc_nvlist_src = zc->zc_nvlist_src;
239 zcdm_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
240 zcdm_c->zc_nvlist_dst = zc->zc_nvlist_dst;
241 zcdm_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
242 zcdm_c->zc_cookie = zc->zc_cookie;
243 zcdm_c->zc_objset_type = zc->zc_objset_type;
244 zcdm_c->zc_perm_action = zc->zc_perm_action;
245 zcdm_c->zc_history = zc->zc_history;
246 zcdm_c->zc_history_len = zc->zc_history_len;
247 zcdm_c->zc_history_offset = zc->zc_history_offset;
248 zcdm_c->zc_obj = zc->zc_obj;
249 zcdm_c->zc_iflags = zc->zc_iflags;
250 zcdm_c->zc_share = zc->zc_share;
251 zcdm_c->zc_jailid = zc->zc_jailid;
252 zcdm_c->zc_objset_stats = zc->zc_objset_stats;
253 zcdm_c->zc_begin_record = zc->zc_begin_record;
254 zcdm_c->zc_defer_destroy = zc->zc_defer_destroy;
255 zcdm_c->zc_temphold = zc->zc_temphold;
256 zcdm_c->zc_action_handle = zc->zc_action_handle;
257 zcdm_c->zc_cleanup_fd = zc->zc_cleanup_fd;
258 zcdm_c->zc_simple = zc->zc_simple;
259 bcopy(zc->zc_pad, zcdm_c->zc_pad, sizeof(zcdm_c->zc_pad));
260 zcdm_c->zc_sendobj = zc->zc_sendobj;
261 zcdm_c->zc_fromobj = zc->zc_fromobj;
262 zcdm_c->zc_createtxg = zc->zc_createtxg;
263 zcdm_c->zc_stat = zc->zc_stat;
265 /* zc_inject_record doesn't change in libzfs_core */
266 zc->zc_inject_record = zcdm_c->zc_inject_record;
268 if (request == ZFS_IOC_RECV)
269 strlcpy(zcdm_c->zc_top_ds,
270 zc->zc_value + strlen(zc->zc_value) + 1,
271 (MAXPATHLEN * 2) - strlen(zc->zc_value) - 1);
275 case ZFS_CMD_COMPAT_V28:
276 zc28_c = (void *)addr;
278 strlcpy(zc28_c->zc_name, zc->zc_name, MAXPATHLEN);
279 strlcpy(zc28_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
280 strlcpy(zc28_c->zc_string, zc->zc_string, MAXPATHLEN);
281 zc28_c->zc_guid = zc->zc_guid;
282 zc28_c->zc_nvlist_conf = zc->zc_nvlist_conf;
283 zc28_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
284 zc28_c->zc_nvlist_src = zc->zc_nvlist_src;
285 zc28_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
286 zc28_c->zc_nvlist_dst = zc->zc_nvlist_dst;
287 zc28_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
288 zc28_c->zc_cookie = zc->zc_cookie;
289 zc28_c->zc_objset_type = zc->zc_objset_type;
290 zc28_c->zc_perm_action = zc->zc_perm_action;
291 zc28_c->zc_history = zc->zc_history;
292 zc28_c->zc_history_len = zc->zc_history_len;
293 zc28_c->zc_history_offset = zc->zc_history_offset;
294 zc28_c->zc_obj = zc->zc_obj;
295 zc28_c->zc_iflags = zc->zc_iflags;
296 zc28_c->zc_share = zc->zc_share;
297 zc28_c->zc_jailid = zc->zc_jailid;
298 zc28_c->zc_objset_stats = zc->zc_objset_stats;
299 zc28_c->zc_begin_record = zc->zc_begin_record;
300 zc28_c->zc_defer_destroy = zc->zc_defer_destroy;
301 zc28_c->zc_temphold = zc->zc_temphold;
302 zc28_c->zc_action_handle = zc->zc_action_handle;
303 zc28_c->zc_cleanup_fd = zc->zc_cleanup_fd;
304 zc28_c->zc_simple = zc->zc_simple;
305 bcopy(zc->zc_pad, zc28_c->zc_pad, sizeof(zc28_c->zc_pad));
306 zc28_c->zc_sendobj = zc->zc_sendobj;
307 zc28_c->zc_fromobj = zc->zc_fromobj;
308 zc28_c->zc_createtxg = zc->zc_createtxg;
309 zc28_c->zc_stat = zc->zc_stat;
311 if (request == ZFS_IOC_RECV)
312 strlcpy(zc28_c->zc_top_ds,
313 zc->zc_value + strlen(zc->zc_value) + 1,
314 MAXPATHLEN * 2 - strlen(zc->zc_value) - 1);
316 /* zc_inject_record */
317 zc28_c->zc_inject_record.zi_objset =
318 zc->zc_inject_record.zi_objset;
319 zc28_c->zc_inject_record.zi_object =
320 zc->zc_inject_record.zi_object;
321 zc28_c->zc_inject_record.zi_start =
322 zc->zc_inject_record.zi_start;
323 zc28_c->zc_inject_record.zi_end =
324 zc->zc_inject_record.zi_end;
325 zc28_c->zc_inject_record.zi_guid =
326 zc->zc_inject_record.zi_guid;
327 zc28_c->zc_inject_record.zi_level =
328 zc->zc_inject_record.zi_level;
329 zc28_c->zc_inject_record.zi_error =
330 zc->zc_inject_record.zi_error;
331 zc28_c->zc_inject_record.zi_type =
332 zc->zc_inject_record.zi_type;
333 zc28_c->zc_inject_record.zi_freq =
334 zc->zc_inject_record.zi_freq;
335 zc28_c->zc_inject_record.zi_failfast =
336 zc->zc_inject_record.zi_failfast;
337 strlcpy(zc28_c->zc_inject_record.zi_func,
338 zc->zc_inject_record.zi_func, MAXNAMELEN);
339 zc28_c->zc_inject_record.zi_iotype =
340 zc->zc_inject_record.zi_iotype;
341 zc28_c->zc_inject_record.zi_duration =
342 zc->zc_inject_record.zi_duration;
343 zc28_c->zc_inject_record.zi_timer =
344 zc->zc_inject_record.zi_timer;
347 case ZFS_CMD_COMPAT_V15:
351 strlcpy(zc_c->zc_name, zc->zc_name, MAXPATHLEN);
352 strlcpy(zc_c->zc_value, zc->zc_value, MAXPATHLEN);
353 strlcpy(zc_c->zc_string, zc->zc_string, MAXPATHLEN);
354 zc_c->zc_guid = zc->zc_guid;
355 zc_c->zc_nvlist_conf = zc->zc_nvlist_conf;
356 zc_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
357 zc_c->zc_nvlist_src = zc->zc_nvlist_src;
358 zc_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
359 zc_c->zc_nvlist_dst = zc->zc_nvlist_dst;
360 zc_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
361 zc_c->zc_cookie = zc->zc_cookie;
362 zc_c->zc_objset_type = zc->zc_objset_type;
363 zc_c->zc_perm_action = zc->zc_perm_action;
364 zc_c->zc_history = zc->zc_history;
365 zc_c->zc_history_len = zc->zc_history_len;
366 zc_c->zc_history_offset = zc->zc_history_offset;
367 zc_c->zc_obj = zc->zc_obj;
368 zc_c->zc_share = zc->zc_share;
369 zc_c->zc_jailid = zc->zc_jailid;
370 zc_c->zc_objset_stats = zc->zc_objset_stats;
371 zc_c->zc_begin_record = zc->zc_begin_record;
373 /* zc_inject_record */
374 zc_c->zc_inject_record.zi_objset =
375 zc->zc_inject_record.zi_objset;
376 zc_c->zc_inject_record.zi_object =
377 zc->zc_inject_record.zi_object;
378 zc_c->zc_inject_record.zi_start =
379 zc->zc_inject_record.zi_start;
380 zc_c->zc_inject_record.zi_end =
381 zc->zc_inject_record.zi_end;
382 zc_c->zc_inject_record.zi_guid =
383 zc->zc_inject_record.zi_guid;
384 zc_c->zc_inject_record.zi_level =
385 zc->zc_inject_record.zi_level;
386 zc_c->zc_inject_record.zi_error =
387 zc->zc_inject_record.zi_error;
388 zc_c->zc_inject_record.zi_type =
389 zc->zc_inject_record.zi_type;
390 zc_c->zc_inject_record.zi_freq =
391 zc->zc_inject_record.zi_freq;
392 zc_c->zc_inject_record.zi_failfast =
393 zc->zc_inject_record.zi_failfast;
400 zfs_ioctl_compat_get_nvlist(uint64_t nvl, size_t size, int iflag,
405 nvlist_t *list = NULL;
408 * Read in and unpack the user-supplied nvlist.
414 packed = kmem_alloc(size, KM_SLEEP);
415 if ((error = ddi_copyin((void *)(uintptr_t)nvl, packed, size,
417 kmem_free(packed, size);
421 packed = (void *)(uintptr_t)nvl;
424 error = nvlist_unpack(packed, size, &list, 0);
427 kmem_free(packed, size);
438 zfs_ioctl_compat_put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
444 VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0);
447 packed = kmem_alloc(size, KM_SLEEP);
448 VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
451 if (ddi_copyout(packed,
452 (void *)(uintptr_t)zc->zc_nvlist_dst, size, zc->zc_iflags) != 0)
454 kmem_free(packed, size);
456 packed = (void *)(uintptr_t)zc->zc_nvlist_dst;
457 VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
461 zc->zc_nvlist_dst_size = size;
466 zfs_ioctl_compat_fix_stats_nvlist(nvlist_t *nvl)
469 nvlist_t *nvroot = NULL;
471 uint_t c, children, nelem;
473 if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_CHILDREN,
474 &child, &children) == 0) {
475 for (c = 0; c < children; c++) {
476 zfs_ioctl_compat_fix_stats_nvlist(child[c]);
480 if (nvlist_lookup_nvlist(nvl, ZPOOL_CONFIG_VDEV_TREE,
482 zfs_ioctl_compat_fix_stats_nvlist(nvroot);
484 if ((nvlist_lookup_uint64_array(nvl, ZPOOL_CONFIG_VDEV_STATS,
486 if ((nvlist_lookup_uint64_array(nvl, "stats",
489 (uint64_t **)&vs, &nelem) == 0)) {
490 nvlist_add_uint64_array(nvl,
494 ZPOOL_CONFIG_VDEV_STATS,
496 (uint64_t *)vs, nelem);
498 nvlist_remove(nvl, ZPOOL_CONFIG_VDEV_STATS,
500 nvlist_remove(nvl, "stats",
502 DATA_TYPE_UINT64_ARRAY);
507 zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int nc)
509 nvlist_t *nv, *nvp = NULL;
513 if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst,
514 zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
517 if (nc == 5) { /* ZFS_IOC_POOL_STATS */
519 while ((elem = nvlist_next_nvpair(nv, elem)) != NULL) {
520 if (nvpair_value_nvlist(elem, &nvp) == 0)
521 zfs_ioctl_compat_fix_stats_nvlist(nvp);
525 zfs_ioctl_compat_fix_stats_nvlist(nv);
527 error = zfs_ioctl_compat_put_nvlist(zc, nv);
535 zfs_ioctl_compat_pool_get_props(zfs_cmd_t *zc)
537 nvlist_t *nv, *nva = NULL;
540 if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst,
541 zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
545 if (nvlist_lookup_nvlist(nv, "allocated", &nva) == 0) {
546 nvlist_add_nvlist(nv, "used", nva);
547 nvlist_remove(nv, "allocated", DATA_TYPE_NVLIST);
550 if (nvlist_lookup_nvlist(nv, "free", &nva) == 0) {
551 nvlist_add_nvlist(nv, "available", nva);
552 nvlist_remove(nv, "free", DATA_TYPE_NVLIST);
555 if (nvlist_lookup_nvlist(nv, "used", &nva) == 0) {
556 nvlist_add_nvlist(nv, "allocated", nva);
557 nvlist_remove(nv, "used", DATA_TYPE_NVLIST);
560 if (nvlist_lookup_nvlist(nv, "available", &nva) == 0) {
561 nvlist_add_nvlist(nv, "free", nva);
562 nvlist_remove(nv, "available", DATA_TYPE_NVLIST);
566 error = zfs_ioctl_compat_put_nvlist(zc, nv);
575 zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag)
583 case ZFS_CMD_COMPAT_NONE:
584 ncmd = _IOWR('Z', request, struct zfs_iocparm);
585 zp.zfs_cmd = (uint64_t)zc;
586 zp.zfs_cmd_size = sizeof(zfs_cmd_t);
587 zp.zfs_ioctl_version = ZFS_IOCVER_CURRENT;
588 return (ioctl(fd, ncmd, &zp));
589 case ZFS_CMD_COMPAT_LZC:
590 ncmd = _IOWR('Z', request, struct zfs_cmd);
591 return (ioctl(fd, ncmd, zc));
592 case ZFS_CMD_COMPAT_DEADMAN:
593 zc_c = malloc(sizeof(zfs_cmd_deadman_t));
594 ncmd = _IOWR('Z', request, struct zfs_cmd_deadman);
596 case ZFS_CMD_COMPAT_V28:
597 zc_c = malloc(sizeof(zfs_cmd_v28_t));
598 ncmd = _IOWR('Z', request, struct zfs_cmd_v28);
600 case ZFS_CMD_COMPAT_V15:
601 nc = zfs_ioctl_v28_to_v15[request];
602 zc_c = malloc(sizeof(zfs_cmd_v15_t));
603 ncmd = _IOWR('Z', nc, struct zfs_cmd_v15);
609 if (ZFS_IOCREQ(ncmd) == ZFS_IOC_COMPAT_FAIL)
612 zfs_cmd_compat_put(zc, (caddr_t)zc_c, request, cflag);
614 ret = ioctl(fd, ncmd, zc_c);
615 if (cflag == ZFS_CMD_COMPAT_V15 &&
616 nc == ZFS_IOC_POOL_IMPORT)
617 ret = ioctl(fd, _IOWR('Z', ZFS_IOC_POOL_CONFIGS,
618 struct zfs_cmd_v15), zc_c);
619 zfs_cmd_compat_get(zc, (caddr_t)zc_c, cflag);
622 if (cflag == ZFS_CMD_COMPAT_V15) {
624 case ZFS_IOC_POOL_IMPORT:
625 case ZFS_IOC_POOL_CONFIGS:
626 case ZFS_IOC_POOL_STATS:
627 case ZFS_IOC_POOL_TRYIMPORT:
628 zfs_ioctl_compat_fix_stats(zc, nc);
630 case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
631 zfs_ioctl_compat_pool_get_props(zc);
640 zfs_ioctl_compat_pre(zfs_cmd_t *zc, int *vec, const int cflag)
644 /* are we creating a clone? */
645 if (*vec == ZFS_IOC_CREATE && zc->zc_value[0] != '\0')
646 *vec = ZFS_IOC_CLONE;
648 if (cflag == ZFS_CMD_COMPAT_V15) {
651 case 7: /* ZFS_IOC_POOL_SCRUB (v15) */
652 zc->zc_cookie = POOL_SCAN_SCRUB;
661 zfs_ioctl_compat_post(zfs_cmd_t *zc, int vec, const int cflag)
663 if (cflag == ZFS_CMD_COMPAT_V15) {
665 case ZFS_IOC_POOL_CONFIGS:
666 case ZFS_IOC_POOL_STATS:
667 case ZFS_IOC_POOL_TRYIMPORT:
668 zfs_ioctl_compat_fix_stats(zc, vec);
670 case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
671 zfs_ioctl_compat_pool_get_props(zc);
678 zfs_ioctl_compat_innvl(zfs_cmd_t *zc, nvlist_t * innvl, const int vec,
681 nvlist_t *nvl, *tmpnvl, *hnvl;
683 char *poolname, *snapname;
686 if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC)
691 nvl = fnvlist_alloc();
692 fnvlist_add_int32(nvl, "type", zc->zc_objset_type);
694 fnvlist_add_nvlist(nvl, "props", innvl);
700 nvl = fnvlist_alloc();
701 fnvlist_add_string(nvl, "origin", zc->zc_value);
703 fnvlist_add_nvlist(nvl, "props", innvl);
708 case ZFS_IOC_SNAPSHOT:
711 nvl = fnvlist_alloc();
712 fnvlist_add_nvlist(nvl, "props", innvl);
713 tmpnvl = fnvlist_alloc();
714 snapname = kmem_asprintf("%s@%s", zc->zc_name, zc->zc_value);
715 fnvlist_add_boolean(tmpnvl, snapname);
716 kmem_free(snapname, strlen(snapname + 1));
717 /* check if we are doing a recursive snapshot */
719 dmu_get_recursive_snaps_nvl(zc->zc_name, zc->zc_value,
721 fnvlist_add_nvlist(nvl, "snaps", tmpnvl);
722 fnvlist_free(tmpnvl);
724 /* strip dataset part from zc->zc_name */
725 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
728 case ZFS_IOC_SPACE_SNAPS:
729 nvl = fnvlist_alloc();
730 fnvlist_add_string(nvl, "firstsnap", zc->zc_value);
735 case ZFS_IOC_DESTROY_SNAPS:
736 if (innvl == NULL && cflag == ZFS_CMD_COMPAT_DEADMAN)
738 nvl = fnvlist_alloc();
740 fnvlist_add_nvlist(nvl, "snaps", innvl);
743 * We are probably called by even older binaries,
744 * allocate and populate nvlist with recursive
747 if (zfs_component_namecheck(zc->zc_value, NULL,
749 tmpnvl = fnvlist_alloc();
750 if (dmu_get_recursive_snaps_nvl(zc->zc_name,
751 zc->zc_value, tmpnvl) == 0)
752 fnvlist_add_nvlist(nvl, "snaps",
759 /* strip dataset part from zc->zc_name */
760 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
764 nvl = fnvlist_alloc();
765 tmpnvl = fnvlist_alloc();
766 if (zc->zc_cleanup_fd != -1)
767 fnvlist_add_int32(nvl, "cleanup_fd",
768 (int32_t)zc->zc_cleanup_fd);
770 hnvl = fnvlist_alloc();
771 if (dmu_get_recursive_snaps_nvl(zc->zc_name,
772 zc->zc_value, hnvl) == 0) {
774 while ((elem = nvlist_next_nvpair(hnvl,
776 nvlist_add_string(tmpnvl,
777 nvpair_name(elem), zc->zc_string);
782 snapname = kmem_asprintf("%s@%s", zc->zc_name,
784 nvlist_add_string(tmpnvl, snapname, zc->zc_string);
785 kmem_free(snapname, strlen(snapname + 1));
787 fnvlist_add_nvlist(nvl, "holds", tmpnvl);
791 /* strip dataset part from zc->zc_name */
792 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
795 case ZFS_IOC_RELEASE:
796 nvl = fnvlist_alloc();
797 tmpnvl = fnvlist_alloc();
799 hnvl = fnvlist_alloc();
800 if (dmu_get_recursive_snaps_nvl(zc->zc_name,
801 zc->zc_value, hnvl) == 0) {
803 while ((elem = nvlist_next_nvpair(hnvl,
805 fnvlist_add_boolean(tmpnvl,
807 fnvlist_add_nvlist(nvl,
808 nvpair_name(elem), tmpnvl);
813 snapname = kmem_asprintf("%s@%s", zc->zc_name,
815 fnvlist_add_boolean(tmpnvl, zc->zc_string);
816 fnvlist_add_nvlist(nvl, snapname, tmpnvl);
817 kmem_free(snapname, strlen(snapname + 1));
822 /* strip dataset part from zc->zc_name */
823 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
832 zfs_ioctl_compat_outnvl(zfs_cmd_t *zc, nvlist_t * outnvl, const int vec,
837 if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC)
841 case ZFS_IOC_SPACE_SNAPS:
842 (void) nvlist_lookup_uint64(outnvl, "used", &zc->zc_cookie);
843 (void) nvlist_lookup_uint64(outnvl, "compressed",
844 &zc->zc_objset_type);
845 (void) nvlist_lookup_uint64(outnvl, "uncompressed",
846 &zc->zc_perm_action);
848 /* return empty outnvl */
849 tmpnvl = fnvlist_alloc();
855 case ZFS_IOC_RELEASE:
857 /* return empty outnvl */
858 tmpnvl = fnvlist_alloc();