]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
MFC r296510, r296563, r296567: MFV r296505:
[FreeBSD/stable/10.git] / sys / cddl / contrib / opensolaris / common / zfs / zfs_ioctl_compat.c
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
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
59         switch (cflag) {
60         case ZFS_CMD_COMPAT_RESUME:
61                 resume_c = (void *)addr;
62                 /* zc */
63                 strlcpy(zc->zc_name, resume_c->zc_name, MAXPATHLEN);
64                 strlcpy(zc->zc_value, resume_c->zc_value, MAXPATHLEN * 2);
65                 strlcpy(zc->zc_string, resume_c->zc_string, MAXPATHLEN);
66
67 #define FIELD_COPY(field) zc->field = resume_c->field
68                 FIELD_COPY(zc_nvlist_src);
69                 FIELD_COPY(zc_nvlist_src_size);
70                 FIELD_COPY(zc_nvlist_dst);
71                 FIELD_COPY(zc_nvlist_dst_size);
72                 FIELD_COPY(zc_nvlist_dst_filled);
73                 FIELD_COPY(zc_pad2);
74                 FIELD_COPY(zc_history);
75                 FIELD_COPY(zc_guid);
76                 FIELD_COPY(zc_nvlist_conf);
77                 FIELD_COPY(zc_nvlist_conf_size);
78                 FIELD_COPY(zc_cookie);
79                 FIELD_COPY(zc_objset_type);
80                 FIELD_COPY(zc_perm_action);
81                 FIELD_COPY(zc_history_len);
82                 FIELD_COPY(zc_history_offset);
83                 FIELD_COPY(zc_obj);
84                 FIELD_COPY(zc_iflags);
85                 FIELD_COPY(zc_share);
86                 FIELD_COPY(zc_jailid);
87                 FIELD_COPY(zc_objset_stats);
88                 FIELD_COPY(zc_begin_record);
89                 FIELD_COPY(zc_inject_record.zi_objset);
90                 FIELD_COPY(zc_inject_record.zi_object);
91                 FIELD_COPY(zc_inject_record.zi_start);
92                 FIELD_COPY(zc_inject_record.zi_end);
93                 FIELD_COPY(zc_inject_record.zi_guid);
94                 FIELD_COPY(zc_inject_record.zi_level);
95                 FIELD_COPY(zc_inject_record.zi_error);
96                 FIELD_COPY(zc_inject_record.zi_type);
97                 FIELD_COPY(zc_inject_record.zi_freq);
98                 FIELD_COPY(zc_inject_record.zi_failfast);
99                 strlcpy(zc->zc_inject_record.zi_func,
100                     resume_c->zc_inject_record.zi_func, MAXNAMELEN);
101                 FIELD_COPY(zc_inject_record.zi_iotype);
102                 FIELD_COPY(zc_inject_record.zi_duration);
103                 FIELD_COPY(zc_inject_record.zi_timer);
104                 zc->zc_inject_record.zi_nlanes = 1;
105                 FIELD_COPY(zc_inject_record.zi_cmd);
106                 FIELD_COPY(zc_inject_record.zi_pad);
107                 FIELD_COPY(zc_defer_destroy);
108                 FIELD_COPY(zc_flags);
109                 FIELD_COPY(zc_action_handle);
110                 FIELD_COPY(zc_cleanup_fd);
111                 FIELD_COPY(zc_simple);
112                 FIELD_COPY(zc_resumable);
113                 FIELD_COPY(zc_sendobj);
114                 FIELD_COPY(zc_fromobj);
115                 FIELD_COPY(zc_createtxg);
116                 FIELD_COPY(zc_stat);
117 #undef FIELD_COPY
118                 break;
119
120         case ZFS_CMD_COMPAT_EDBP:
121                 edbp_c = (void *)addr;
122                 /* zc */
123                 strlcpy(zc->zc_name, edbp_c->zc_name, MAXPATHLEN);
124                 strlcpy(zc->zc_value, edbp_c->zc_value, MAXPATHLEN * 2);
125                 strlcpy(zc->zc_string, edbp_c->zc_string, MAXPATHLEN);
126
127 #define FIELD_COPY(field) zc->field = edbp_c->field
128                 FIELD_COPY(zc_nvlist_src);
129                 FIELD_COPY(zc_nvlist_src_size);
130                 FIELD_COPY(zc_nvlist_dst);
131                 FIELD_COPY(zc_nvlist_dst_size);
132                 FIELD_COPY(zc_nvlist_dst_filled);
133                 FIELD_COPY(zc_pad2);
134                 FIELD_COPY(zc_history);
135                 FIELD_COPY(zc_guid);
136                 FIELD_COPY(zc_nvlist_conf);
137                 FIELD_COPY(zc_nvlist_conf_size);
138                 FIELD_COPY(zc_cookie);
139                 FIELD_COPY(zc_objset_type);
140                 FIELD_COPY(zc_perm_action);
141                 FIELD_COPY(zc_history_len);
142                 FIELD_COPY(zc_history_offset);
143                 FIELD_COPY(zc_obj);
144                 FIELD_COPY(zc_iflags);
145                 FIELD_COPY(zc_share);
146                 FIELD_COPY(zc_jailid);
147                 FIELD_COPY(zc_objset_stats);
148                 zc->zc_begin_record.drr_u.drr_begin = edbp_c->zc_begin_record;
149                 FIELD_COPY(zc_inject_record.zi_objset);
150                 FIELD_COPY(zc_inject_record.zi_object);
151                 FIELD_COPY(zc_inject_record.zi_start);
152                 FIELD_COPY(zc_inject_record.zi_end);
153                 FIELD_COPY(zc_inject_record.zi_guid);
154                 FIELD_COPY(zc_inject_record.zi_level);
155                 FIELD_COPY(zc_inject_record.zi_error);
156                 FIELD_COPY(zc_inject_record.zi_type);
157                 FIELD_COPY(zc_inject_record.zi_freq);
158                 FIELD_COPY(zc_inject_record.zi_failfast);
159                 strlcpy(zc->zc_inject_record.zi_func,
160                     edbp_c->zc_inject_record.zi_func, MAXNAMELEN);
161                 FIELD_COPY(zc_inject_record.zi_iotype);
162                 FIELD_COPY(zc_inject_record.zi_duration);
163                 FIELD_COPY(zc_inject_record.zi_timer);
164                 zc->zc_inject_record.zi_nlanes = 1;
165                 FIELD_COPY(zc_inject_record.zi_cmd);
166                 FIELD_COPY(zc_inject_record.zi_pad);
167                 FIELD_COPY(zc_defer_destroy);
168                 FIELD_COPY(zc_flags);
169                 FIELD_COPY(zc_action_handle);
170                 FIELD_COPY(zc_cleanup_fd);
171                 FIELD_COPY(zc_simple);
172                 zc->zc_resumable = B_FALSE;
173                 FIELD_COPY(zc_sendobj);
174                 FIELD_COPY(zc_fromobj);
175                 FIELD_COPY(zc_createtxg);
176                 FIELD_COPY(zc_stat);
177 #undef FIELD_COPY
178                 break;
179
180         case ZFS_CMD_COMPAT_ZCMD:
181                 zcmd_c = (void *)addr;
182                 /* zc */
183                 strlcpy(zc->zc_name, zcmd_c->zc_name, MAXPATHLEN);
184                 strlcpy(zc->zc_value, zcmd_c->zc_value, MAXPATHLEN * 2);
185                 strlcpy(zc->zc_string, zcmd_c->zc_string, MAXPATHLEN);
186
187 #define FIELD_COPY(field) zc->field = zcmd_c->field
188                 FIELD_COPY(zc_nvlist_src);
189                 FIELD_COPY(zc_nvlist_src_size);
190                 FIELD_COPY(zc_nvlist_dst);
191                 FIELD_COPY(zc_nvlist_dst_size);
192                 FIELD_COPY(zc_nvlist_dst_filled);
193                 FIELD_COPY(zc_pad2);
194                 FIELD_COPY(zc_history);
195                 FIELD_COPY(zc_guid);
196                 FIELD_COPY(zc_nvlist_conf);
197                 FIELD_COPY(zc_nvlist_conf_size);
198                 FIELD_COPY(zc_cookie);
199                 FIELD_COPY(zc_objset_type);
200                 FIELD_COPY(zc_perm_action);
201                 FIELD_COPY(zc_history_len);
202                 FIELD_COPY(zc_history_offset);
203                 FIELD_COPY(zc_obj);
204                 FIELD_COPY(zc_iflags);
205                 FIELD_COPY(zc_share);
206                 FIELD_COPY(zc_jailid);
207                 FIELD_COPY(zc_objset_stats);
208                 zc->zc_begin_record.drr_u.drr_begin = zcmd_c->zc_begin_record;
209                 FIELD_COPY(zc_inject_record.zi_objset);
210                 FIELD_COPY(zc_inject_record.zi_object);
211                 FIELD_COPY(zc_inject_record.zi_start);
212                 FIELD_COPY(zc_inject_record.zi_end);
213                 FIELD_COPY(zc_inject_record.zi_guid);
214                 FIELD_COPY(zc_inject_record.zi_level);
215                 FIELD_COPY(zc_inject_record.zi_error);
216                 FIELD_COPY(zc_inject_record.zi_type);
217                 FIELD_COPY(zc_inject_record.zi_freq);
218                 FIELD_COPY(zc_inject_record.zi_failfast);
219                 strlcpy(zc->zc_inject_record.zi_func,
220                     zcmd_c->zc_inject_record.zi_func, MAXNAMELEN);
221                 FIELD_COPY(zc_inject_record.zi_iotype);
222                 FIELD_COPY(zc_inject_record.zi_duration);
223                 FIELD_COPY(zc_inject_record.zi_timer);
224                 zc->zc_inject_record.zi_nlanes = 1;
225                 FIELD_COPY(zc_inject_record.zi_cmd);
226                 FIELD_COPY(zc_inject_record.zi_pad);
227
228                 /* boolean_t -> uint32_t */
229                 zc->zc_defer_destroy = (uint32_t)(zcmd_c->zc_defer_destroy);
230                 zc->zc_flags = 0;
231
232                 FIELD_COPY(zc_action_handle);
233                 FIELD_COPY(zc_cleanup_fd);
234                 FIELD_COPY(zc_simple);
235                 zc->zc_resumable = B_FALSE;
236                 FIELD_COPY(zc_sendobj);
237                 FIELD_COPY(zc_fromobj);
238                 FIELD_COPY(zc_createtxg);
239                 FIELD_COPY(zc_stat);
240 #undef FIELD_COPY
241
242                 break;
243
244         case ZFS_CMD_COMPAT_DEADMAN:
245                 zcdm_c = (void *)addr;
246                 /* zc */
247                 strlcpy(zc->zc_name, zcdm_c->zc_name, MAXPATHLEN);
248                 strlcpy(zc->zc_value, zcdm_c->zc_value, MAXPATHLEN * 2);
249                 strlcpy(zc->zc_string, zcdm_c->zc_string, MAXPATHLEN);
250
251 #define FIELD_COPY(field) zc->field = zcdm_c->field
252                 zc->zc_guid = zcdm_c->zc_guid;
253                 zc->zc_nvlist_conf = zcdm_c->zc_nvlist_conf;
254                 zc->zc_nvlist_conf_size = zcdm_c->zc_nvlist_conf_size;
255                 zc->zc_nvlist_src = zcdm_c->zc_nvlist_src;
256                 zc->zc_nvlist_src_size = zcdm_c->zc_nvlist_src_size;
257                 zc->zc_nvlist_dst = zcdm_c->zc_nvlist_dst;
258                 zc->zc_nvlist_dst_size = zcdm_c->zc_nvlist_dst_size;
259                 zc->zc_cookie = zcdm_c->zc_cookie;
260                 zc->zc_objset_type = zcdm_c->zc_objset_type;
261                 zc->zc_perm_action = zcdm_c->zc_perm_action;
262                 zc->zc_history = zcdm_c->zc_history;
263                 zc->zc_history_len = zcdm_c->zc_history_len;
264                 zc->zc_history_offset = zcdm_c->zc_history_offset;
265                 zc->zc_obj = zcdm_c->zc_obj;
266                 zc->zc_iflags = zcdm_c->zc_iflags;
267                 zc->zc_share = zcdm_c->zc_share;
268                 zc->zc_jailid = zcdm_c->zc_jailid;
269                 zc->zc_objset_stats = zcdm_c->zc_objset_stats;
270                 zc->zc_begin_record.drr_u.drr_begin = zcdm_c->zc_begin_record;
271                 zc->zc_defer_destroy = zcdm_c->zc_defer_destroy;
272                 (void)zcdm_c->zc_temphold;
273                 zc->zc_action_handle = zcdm_c->zc_action_handle;
274                 zc->zc_cleanup_fd = zcdm_c->zc_cleanup_fd;
275                 zc->zc_simple = zcdm_c->zc_simple;
276                 zc->zc_resumable = B_FALSE;
277                 zc->zc_sendobj = zcdm_c->zc_sendobj;
278                 zc->zc_fromobj = zcdm_c->zc_fromobj;
279                 zc->zc_createtxg = zcdm_c->zc_createtxg;
280                 zc->zc_stat = zcdm_c->zc_stat;
281                 FIELD_COPY(zc_inject_record.zi_objset);
282                 FIELD_COPY(zc_inject_record.zi_object);
283                 FIELD_COPY(zc_inject_record.zi_start);
284                 FIELD_COPY(zc_inject_record.zi_end);
285                 FIELD_COPY(zc_inject_record.zi_guid);
286                 FIELD_COPY(zc_inject_record.zi_level);
287                 FIELD_COPY(zc_inject_record.zi_error);
288                 FIELD_COPY(zc_inject_record.zi_type);
289                 FIELD_COPY(zc_inject_record.zi_freq);
290                 FIELD_COPY(zc_inject_record.zi_failfast);
291                 strlcpy(zc->zc_inject_record.zi_func,
292                     resume_c->zc_inject_record.zi_func, MAXNAMELEN);
293                 FIELD_COPY(zc_inject_record.zi_iotype);
294                 FIELD_COPY(zc_inject_record.zi_duration);
295                 FIELD_COPY(zc_inject_record.zi_timer);
296                 zc->zc_inject_record.zi_nlanes = 1;
297                 FIELD_COPY(zc_inject_record.zi_cmd);
298                 FIELD_COPY(zc_inject_record.zi_pad);
299
300                 /* we always assume zc_nvlist_dst_filled is true */
301                 zc->zc_nvlist_dst_filled = B_TRUE;
302 #undef FIELD_COPY
303                 break;
304
305         case ZFS_CMD_COMPAT_V28:
306                 zc28_c = (void *)addr;
307
308                 /* zc */
309                 strlcpy(zc->zc_name, zc28_c->zc_name, MAXPATHLEN);
310                 strlcpy(zc->zc_value, zc28_c->zc_value, MAXPATHLEN * 2);
311                 strlcpy(zc->zc_string, zc28_c->zc_string, MAXPATHLEN);
312                 zc->zc_guid = zc28_c->zc_guid;
313                 zc->zc_nvlist_conf = zc28_c->zc_nvlist_conf;
314                 zc->zc_nvlist_conf_size = zc28_c->zc_nvlist_conf_size;
315                 zc->zc_nvlist_src = zc28_c->zc_nvlist_src;
316                 zc->zc_nvlist_src_size = zc28_c->zc_nvlist_src_size;
317                 zc->zc_nvlist_dst = zc28_c->zc_nvlist_dst;
318                 zc->zc_nvlist_dst_size = zc28_c->zc_nvlist_dst_size;
319                 zc->zc_cookie = zc28_c->zc_cookie;
320                 zc->zc_objset_type = zc28_c->zc_objset_type;
321                 zc->zc_perm_action = zc28_c->zc_perm_action;
322                 zc->zc_history = zc28_c->zc_history;
323                 zc->zc_history_len = zc28_c->zc_history_len;
324                 zc->zc_history_offset = zc28_c->zc_history_offset;
325                 zc->zc_obj = zc28_c->zc_obj;
326                 zc->zc_iflags = zc28_c->zc_iflags;
327                 zc->zc_share = zc28_c->zc_share;
328                 zc->zc_jailid = zc28_c->zc_jailid;
329                 zc->zc_objset_stats = zc28_c->zc_objset_stats;
330                 zc->zc_begin_record.drr_u.drr_begin = zc28_c->zc_begin_record;
331                 zc->zc_defer_destroy = zc28_c->zc_defer_destroy;
332                 (void)zc28_c->zc_temphold;
333                 zc->zc_action_handle = zc28_c->zc_action_handle;
334                 zc->zc_cleanup_fd = zc28_c->zc_cleanup_fd;
335                 zc->zc_simple = zc28_c->zc_simple;
336                 zc->zc_resumable = B_FALSE;
337                 zc->zc_sendobj = zc28_c->zc_sendobj;
338                 zc->zc_fromobj = zc28_c->zc_fromobj;
339                 zc->zc_createtxg = zc28_c->zc_createtxg;
340                 zc->zc_stat = zc28_c->zc_stat;
341
342                 /* zc->zc_inject_record */
343                 zc->zc_inject_record.zi_objset =
344                     zc28_c->zc_inject_record.zi_objset;
345                 zc->zc_inject_record.zi_object =
346                     zc28_c->zc_inject_record.zi_object;
347                 zc->zc_inject_record.zi_start =
348                     zc28_c->zc_inject_record.zi_start;
349                 zc->zc_inject_record.zi_end =
350                     zc28_c->zc_inject_record.zi_end;
351                 zc->zc_inject_record.zi_guid =
352                     zc28_c->zc_inject_record.zi_guid;
353                 zc->zc_inject_record.zi_level =
354                     zc28_c->zc_inject_record.zi_level;
355                 zc->zc_inject_record.zi_error =
356                     zc28_c->zc_inject_record.zi_error;
357                 zc->zc_inject_record.zi_type =
358                     zc28_c->zc_inject_record.zi_type;
359                 zc->zc_inject_record.zi_freq =
360                     zc28_c->zc_inject_record.zi_freq;
361                 zc->zc_inject_record.zi_failfast =
362                     zc28_c->zc_inject_record.zi_failfast;
363                 strlcpy(zc->zc_inject_record.zi_func,
364                     zc28_c->zc_inject_record.zi_func, MAXNAMELEN);
365                 zc->zc_inject_record.zi_iotype =
366                     zc28_c->zc_inject_record.zi_iotype;
367                 zc->zc_inject_record.zi_duration =
368                     zc28_c->zc_inject_record.zi_duration;
369                 zc->zc_inject_record.zi_timer =
370                     zc28_c->zc_inject_record.zi_timer;
371                 zc->zc_inject_record.zi_nlanes = 1;
372                 zc->zc_inject_record.zi_cmd = ZINJECT_UNINITIALIZED;
373                 zc->zc_inject_record.zi_pad = 0;
374                 break;
375
376         case ZFS_CMD_COMPAT_V15:
377                 zc_c = (void *)addr;
378
379                 /* zc */
380                 strlcpy(zc->zc_name, zc_c->zc_name, MAXPATHLEN);
381                 strlcpy(zc->zc_value, zc_c->zc_value, MAXPATHLEN);
382                 strlcpy(zc->zc_string, zc_c->zc_string, MAXPATHLEN);
383                 zc->zc_guid = zc_c->zc_guid;
384                 zc->zc_nvlist_conf = zc_c->zc_nvlist_conf;
385                 zc->zc_nvlist_conf_size = zc_c->zc_nvlist_conf_size;
386                 zc->zc_nvlist_src = zc_c->zc_nvlist_src;
387                 zc->zc_nvlist_src_size = zc_c->zc_nvlist_src_size;
388                 zc->zc_nvlist_dst = zc_c->zc_nvlist_dst;
389                 zc->zc_nvlist_dst_size = zc_c->zc_nvlist_dst_size;
390                 zc->zc_cookie = zc_c->zc_cookie;
391                 zc->zc_objset_type = zc_c->zc_objset_type;
392                 zc->zc_perm_action = zc_c->zc_perm_action;
393                 zc->zc_history = zc_c->zc_history;
394                 zc->zc_history_len = zc_c->zc_history_len;
395                 zc->zc_history_offset = zc_c->zc_history_offset;
396                 zc->zc_obj = zc_c->zc_obj;
397                 zc->zc_share = zc_c->zc_share;
398                 zc->zc_jailid = zc_c->zc_jailid;
399                 zc->zc_objset_stats = zc_c->zc_objset_stats;
400                 zc->zc_begin_record.drr_u.drr_begin = zc_c->zc_begin_record;
401
402                 /* zc->zc_inject_record */
403                 zc->zc_inject_record.zi_objset =
404                     zc_c->zc_inject_record.zi_objset;
405                 zc->zc_inject_record.zi_object =
406                     zc_c->zc_inject_record.zi_object;
407                 zc->zc_inject_record.zi_start =
408                     zc_c->zc_inject_record.zi_start;
409                 zc->zc_inject_record.zi_end =
410                     zc_c->zc_inject_record.zi_end;
411                 zc->zc_inject_record.zi_guid =
412                     zc_c->zc_inject_record.zi_guid;
413                 zc->zc_inject_record.zi_level =
414                     zc_c->zc_inject_record.zi_level;
415                 zc->zc_inject_record.zi_error =
416                     zc_c->zc_inject_record.zi_error;
417                 zc->zc_inject_record.zi_type =
418                     zc_c->zc_inject_record.zi_type;
419                 zc->zc_inject_record.zi_freq =
420                     zc_c->zc_inject_record.zi_freq;
421                 zc->zc_inject_record.zi_failfast =
422                     zc_c->zc_inject_record.zi_failfast;
423                 break;
424         }
425 }
426
427 void
428 zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_t addr, const int request,
429     const int cflag)
430 {
431         zfs_cmd_v15_t *zc_c;
432         zfs_cmd_v28_t *zc28_c;
433         zfs_cmd_deadman_t *zcdm_c;
434         zfs_cmd_zcmd_t *zcmd_c;
435         zfs_cmd_edbp_t *edbp_c;
436         zfs_cmd_resume_t *resume_c;
437
438         switch (cflag) {
439         case ZFS_CMD_COMPAT_RESUME:
440                 resume_c = (void *)addr;
441                 strlcpy(resume_c->zc_name, zc->zc_name, MAXPATHLEN);
442                 strlcpy(resume_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
443                 strlcpy(resume_c->zc_string, zc->zc_string, MAXPATHLEN);
444
445 #define FIELD_COPY(field) resume_c->field = zc->field
446                 FIELD_COPY(zc_nvlist_src);
447                 FIELD_COPY(zc_nvlist_src_size);
448                 FIELD_COPY(zc_nvlist_dst);
449                 FIELD_COPY(zc_nvlist_dst_size);
450                 FIELD_COPY(zc_nvlist_dst_filled);
451                 FIELD_COPY(zc_pad2);
452                 FIELD_COPY(zc_history);
453                 FIELD_COPY(zc_guid);
454                 FIELD_COPY(zc_nvlist_conf);
455                 FIELD_COPY(zc_nvlist_conf_size);
456                 FIELD_COPY(zc_cookie);
457                 FIELD_COPY(zc_objset_type);
458                 FIELD_COPY(zc_perm_action);
459                 FIELD_COPY(zc_history_len);
460                 FIELD_COPY(zc_history_offset);
461                 FIELD_COPY(zc_obj);
462                 FIELD_COPY(zc_iflags);
463                 FIELD_COPY(zc_share);
464                 FIELD_COPY(zc_jailid);
465                 FIELD_COPY(zc_objset_stats);
466                 FIELD_COPY(zc_begin_record);
467                 FIELD_COPY(zc_inject_record.zi_objset);
468                 FIELD_COPY(zc_inject_record.zi_object);
469                 FIELD_COPY(zc_inject_record.zi_start);
470                 FIELD_COPY(zc_inject_record.zi_end);
471                 FIELD_COPY(zc_inject_record.zi_guid);
472                 FIELD_COPY(zc_inject_record.zi_level);
473                 FIELD_COPY(zc_inject_record.zi_error);
474                 FIELD_COPY(zc_inject_record.zi_type);
475                 FIELD_COPY(zc_inject_record.zi_freq);
476                 FIELD_COPY(zc_inject_record.zi_failfast);
477                 strlcpy(resume_c->zc_inject_record.zi_func,
478                     zc->zc_inject_record.zi_func, MAXNAMELEN);
479                 FIELD_COPY(zc_inject_record.zi_iotype);
480                 FIELD_COPY(zc_inject_record.zi_duration);
481                 FIELD_COPY(zc_inject_record.zi_timer);
482                 FIELD_COPY(zc_inject_record.zi_cmd);
483                 FIELD_COPY(zc_inject_record.zi_pad);
484                 FIELD_COPY(zc_defer_destroy);
485                 FIELD_COPY(zc_flags);
486                 FIELD_COPY(zc_action_handle);
487                 FIELD_COPY(zc_cleanup_fd);
488                 FIELD_COPY(zc_simple);
489                 FIELD_COPY(zc_sendobj);
490                 FIELD_COPY(zc_fromobj);
491                 FIELD_COPY(zc_createtxg);
492                 FIELD_COPY(zc_stat);
493 #undef FIELD_COPY
494                 break;
495
496         case ZFS_CMD_COMPAT_EDBP:
497                 edbp_c = (void *)addr;
498                 strlcpy(edbp_c->zc_name, zc->zc_name, MAXPATHLEN);
499                 strlcpy(edbp_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
500                 strlcpy(edbp_c->zc_string, zc->zc_string, MAXPATHLEN);
501
502 #define FIELD_COPY(field) edbp_c->field = zc->field
503                 FIELD_COPY(zc_nvlist_src);
504                 FIELD_COPY(zc_nvlist_src_size);
505                 FIELD_COPY(zc_nvlist_dst);
506                 FIELD_COPY(zc_nvlist_dst_size);
507                 FIELD_COPY(zc_nvlist_dst_filled);
508                 FIELD_COPY(zc_pad2);
509                 FIELD_COPY(zc_history);
510                 FIELD_COPY(zc_guid);
511                 FIELD_COPY(zc_nvlist_conf);
512                 FIELD_COPY(zc_nvlist_conf_size);
513                 FIELD_COPY(zc_cookie);
514                 FIELD_COPY(zc_objset_type);
515                 FIELD_COPY(zc_perm_action);
516                 FIELD_COPY(zc_history_len);
517                 FIELD_COPY(zc_history_offset);
518                 FIELD_COPY(zc_obj);
519                 FIELD_COPY(zc_iflags);
520                 FIELD_COPY(zc_share);
521                 FIELD_COPY(zc_jailid);
522                 FIELD_COPY(zc_objset_stats);
523                 edbp_c->zc_begin_record = zc->zc_begin_record.drr_u.drr_begin;
524                 FIELD_COPY(zc_inject_record.zi_objset);
525                 FIELD_COPY(zc_inject_record.zi_object);
526                 FIELD_COPY(zc_inject_record.zi_start);
527                 FIELD_COPY(zc_inject_record.zi_end);
528                 FIELD_COPY(zc_inject_record.zi_guid);
529                 FIELD_COPY(zc_inject_record.zi_level);
530                 FIELD_COPY(zc_inject_record.zi_error);
531                 FIELD_COPY(zc_inject_record.zi_type);
532                 FIELD_COPY(zc_inject_record.zi_freq);
533                 FIELD_COPY(zc_inject_record.zi_failfast);
534                 strlcpy(resume_c->zc_inject_record.zi_func,
535                     zc->zc_inject_record.zi_func, MAXNAMELEN);
536                 FIELD_COPY(zc_inject_record.zi_iotype);
537                 FIELD_COPY(zc_inject_record.zi_duration);
538                 FIELD_COPY(zc_inject_record.zi_timer);
539                 FIELD_COPY(zc_inject_record.zi_cmd);
540                 FIELD_COPY(zc_inject_record.zi_pad);
541                 FIELD_COPY(zc_defer_destroy);
542                 FIELD_COPY(zc_flags);
543                 FIELD_COPY(zc_action_handle);
544                 FIELD_COPY(zc_cleanup_fd);
545                 FIELD_COPY(zc_simple);
546                 FIELD_COPY(zc_sendobj);
547                 FIELD_COPY(zc_fromobj);
548                 FIELD_COPY(zc_createtxg);
549                 FIELD_COPY(zc_stat);
550 #undef FIELD_COPY
551                 break;
552
553         case ZFS_CMD_COMPAT_ZCMD:
554                 zcmd_c = (void *)addr;
555                 /* zc */
556                 strlcpy(zcmd_c->zc_name, zc->zc_name, MAXPATHLEN);
557                 strlcpy(zcmd_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
558                 strlcpy(zcmd_c->zc_string, zc->zc_string, MAXPATHLEN);
559
560 #define FIELD_COPY(field) zcmd_c->field = zc->field
561                 FIELD_COPY(zc_nvlist_src);
562                 FIELD_COPY(zc_nvlist_src_size);
563                 FIELD_COPY(zc_nvlist_dst);
564                 FIELD_COPY(zc_nvlist_dst_size);
565                 FIELD_COPY(zc_nvlist_dst_filled);
566                 FIELD_COPY(zc_pad2);
567                 FIELD_COPY(zc_history);
568                 FIELD_COPY(zc_guid);
569                 FIELD_COPY(zc_nvlist_conf);
570                 FIELD_COPY(zc_nvlist_conf_size);
571                 FIELD_COPY(zc_cookie);
572                 FIELD_COPY(zc_objset_type);
573                 FIELD_COPY(zc_perm_action);
574                 FIELD_COPY(zc_history_len);
575                 FIELD_COPY(zc_history_offset);
576                 FIELD_COPY(zc_obj);
577                 FIELD_COPY(zc_iflags);
578                 FIELD_COPY(zc_share);
579                 FIELD_COPY(zc_jailid);
580                 FIELD_COPY(zc_objset_stats);
581                 zcmd_c->zc_begin_record = zc->zc_begin_record.drr_u.drr_begin;
582                 FIELD_COPY(zc_inject_record.zi_objset);
583                 FIELD_COPY(zc_inject_record.zi_object);
584                 FIELD_COPY(zc_inject_record.zi_start);
585                 FIELD_COPY(zc_inject_record.zi_end);
586                 FIELD_COPY(zc_inject_record.zi_guid);
587                 FIELD_COPY(zc_inject_record.zi_level);
588                 FIELD_COPY(zc_inject_record.zi_error);
589                 FIELD_COPY(zc_inject_record.zi_type);
590                 FIELD_COPY(zc_inject_record.zi_freq);
591                 FIELD_COPY(zc_inject_record.zi_failfast);
592                 strlcpy(resume_c->zc_inject_record.zi_func,
593                     zc->zc_inject_record.zi_func, MAXNAMELEN);
594                 FIELD_COPY(zc_inject_record.zi_iotype);
595                 FIELD_COPY(zc_inject_record.zi_duration);
596                 FIELD_COPY(zc_inject_record.zi_timer);
597                 FIELD_COPY(zc_inject_record.zi_cmd);
598                 FIELD_COPY(zc_inject_record.zi_pad);
599
600                 /* boolean_t -> uint32_t */
601                 zcmd_c->zc_defer_destroy = (uint32_t)(zc->zc_defer_destroy);
602                 zcmd_c->zc_temphold = 0;
603
604                 FIELD_COPY(zc_action_handle);
605                 FIELD_COPY(zc_cleanup_fd);
606                 FIELD_COPY(zc_simple);
607                 FIELD_COPY(zc_sendobj);
608                 FIELD_COPY(zc_fromobj);
609                 FIELD_COPY(zc_createtxg);
610                 FIELD_COPY(zc_stat);
611 #undef FIELD_COPY
612
613                 break;
614
615         case ZFS_CMD_COMPAT_DEADMAN:
616                 zcdm_c = (void *)addr;
617
618                 strlcpy(zcdm_c->zc_name, zc->zc_name, MAXPATHLEN);
619                 strlcpy(zcdm_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
620                 strlcpy(zcdm_c->zc_string, zc->zc_string, MAXPATHLEN);
621
622 #define FIELD_COPY(field) zcdm_c->field = zc->field
623                 zcdm_c->zc_guid = zc->zc_guid;
624                 zcdm_c->zc_nvlist_conf = zc->zc_nvlist_conf;
625                 zcdm_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
626                 zcdm_c->zc_nvlist_src = zc->zc_nvlist_src;
627                 zcdm_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
628                 zcdm_c->zc_nvlist_dst = zc->zc_nvlist_dst;
629                 zcdm_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
630                 zcdm_c->zc_cookie = zc->zc_cookie;
631                 zcdm_c->zc_objset_type = zc->zc_objset_type;
632                 zcdm_c->zc_perm_action = zc->zc_perm_action;
633                 zcdm_c->zc_history = zc->zc_history;
634                 zcdm_c->zc_history_len = zc->zc_history_len;
635                 zcdm_c->zc_history_offset = zc->zc_history_offset;
636                 zcdm_c->zc_obj = zc->zc_obj;
637                 zcdm_c->zc_iflags = zc->zc_iflags;
638                 zcdm_c->zc_share = zc->zc_share;
639                 zcdm_c->zc_jailid = zc->zc_jailid;
640                 zcdm_c->zc_objset_stats = zc->zc_objset_stats;
641                 zcdm_c->zc_begin_record = zc->zc_begin_record.drr_u.drr_begin;
642                 zcdm_c->zc_defer_destroy = zc->zc_defer_destroy;
643                 zcdm_c->zc_temphold = 0;
644                 zcdm_c->zc_action_handle = zc->zc_action_handle;
645                 zcdm_c->zc_cleanup_fd = zc->zc_cleanup_fd;
646                 zcdm_c->zc_simple = zc->zc_simple;
647                 zcdm_c->zc_sendobj = zc->zc_sendobj;
648                 zcdm_c->zc_fromobj = zc->zc_fromobj;
649                 zcdm_c->zc_createtxg = zc->zc_createtxg;
650                 zcdm_c->zc_stat = zc->zc_stat;
651                 FIELD_COPY(zc_inject_record.zi_objset);
652                 FIELD_COPY(zc_inject_record.zi_object);
653                 FIELD_COPY(zc_inject_record.zi_start);
654                 FIELD_COPY(zc_inject_record.zi_end);
655                 FIELD_COPY(zc_inject_record.zi_guid);
656                 FIELD_COPY(zc_inject_record.zi_level);
657                 FIELD_COPY(zc_inject_record.zi_error);
658                 FIELD_COPY(zc_inject_record.zi_type);
659                 FIELD_COPY(zc_inject_record.zi_freq);
660                 FIELD_COPY(zc_inject_record.zi_failfast);
661                 strlcpy(resume_c->zc_inject_record.zi_func,
662                     zc->zc_inject_record.zi_func, MAXNAMELEN);
663                 FIELD_COPY(zc_inject_record.zi_iotype);
664                 FIELD_COPY(zc_inject_record.zi_duration);
665                 FIELD_COPY(zc_inject_record.zi_timer);
666                 FIELD_COPY(zc_inject_record.zi_cmd);
667                 FIELD_COPY(zc_inject_record.zi_pad);
668 #undef FIELD_COPY
669 #ifndef _KERNEL
670                 if (request == ZFS_IOC_RECV)
671                         strlcpy(zcdm_c->zc_top_ds,
672                             zc->zc_value + strlen(zc->zc_value) + 1,
673                             (MAXPATHLEN * 2) - strlen(zc->zc_value) - 1);
674 #endif
675                 break;
676
677         case ZFS_CMD_COMPAT_V28:
678                 zc28_c = (void *)addr;
679
680                 strlcpy(zc28_c->zc_name, zc->zc_name, MAXPATHLEN);
681                 strlcpy(zc28_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
682                 strlcpy(zc28_c->zc_string, zc->zc_string, MAXPATHLEN);
683                 zc28_c->zc_guid = zc->zc_guid;
684                 zc28_c->zc_nvlist_conf = zc->zc_nvlist_conf;
685                 zc28_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
686                 zc28_c->zc_nvlist_src = zc->zc_nvlist_src;
687                 zc28_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
688                 zc28_c->zc_nvlist_dst = zc->zc_nvlist_dst;
689                 zc28_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
690                 zc28_c->zc_cookie = zc->zc_cookie;
691                 zc28_c->zc_objset_type = zc->zc_objset_type;
692                 zc28_c->zc_perm_action = zc->zc_perm_action;
693                 zc28_c->zc_history = zc->zc_history;
694                 zc28_c->zc_history_len = zc->zc_history_len;
695                 zc28_c->zc_history_offset = zc->zc_history_offset;
696                 zc28_c->zc_obj = zc->zc_obj;
697                 zc28_c->zc_iflags = zc->zc_iflags;
698                 zc28_c->zc_share = zc->zc_share;
699                 zc28_c->zc_jailid = zc->zc_jailid;
700                 zc28_c->zc_objset_stats = zc->zc_objset_stats;
701                 zc28_c->zc_begin_record = zc->zc_begin_record.drr_u.drr_begin;
702                 zc28_c->zc_defer_destroy = zc->zc_defer_destroy;
703                 zc28_c->zc_temphold = 0;
704                 zc28_c->zc_action_handle = zc->zc_action_handle;
705                 zc28_c->zc_cleanup_fd = zc->zc_cleanup_fd;
706                 zc28_c->zc_simple = zc->zc_simple;
707                 zc28_c->zc_sendobj = zc->zc_sendobj;
708                 zc28_c->zc_fromobj = zc->zc_fromobj;
709                 zc28_c->zc_createtxg = zc->zc_createtxg;
710                 zc28_c->zc_stat = zc->zc_stat;
711 #ifndef _KERNEL
712                 if (request == ZFS_IOC_RECV)
713                         strlcpy(zc28_c->zc_top_ds,
714                             zc->zc_value + strlen(zc->zc_value) + 1,
715                             MAXPATHLEN * 2 - strlen(zc->zc_value) - 1);
716 #endif
717                 /* zc_inject_record */
718                 zc28_c->zc_inject_record.zi_objset =
719                     zc->zc_inject_record.zi_objset;
720                 zc28_c->zc_inject_record.zi_object =
721                     zc->zc_inject_record.zi_object;
722                 zc28_c->zc_inject_record.zi_start =
723                     zc->zc_inject_record.zi_start;
724                 zc28_c->zc_inject_record.zi_end =
725                     zc->zc_inject_record.zi_end;
726                 zc28_c->zc_inject_record.zi_guid =
727                     zc->zc_inject_record.zi_guid;
728                 zc28_c->zc_inject_record.zi_level =
729                     zc->zc_inject_record.zi_level;
730                 zc28_c->zc_inject_record.zi_error =
731                     zc->zc_inject_record.zi_error;
732                 zc28_c->zc_inject_record.zi_type =
733                     zc->zc_inject_record.zi_type;
734                 zc28_c->zc_inject_record.zi_freq =
735                     zc->zc_inject_record.zi_freq;
736                 zc28_c->zc_inject_record.zi_failfast =
737                     zc->zc_inject_record.zi_failfast;
738                 strlcpy(zc28_c->zc_inject_record.zi_func,
739                     zc->zc_inject_record.zi_func, MAXNAMELEN);
740                 zc28_c->zc_inject_record.zi_iotype =
741                     zc->zc_inject_record.zi_iotype;
742                 zc28_c->zc_inject_record.zi_duration =
743                     zc->zc_inject_record.zi_duration;
744                 zc28_c->zc_inject_record.zi_timer =
745                     zc->zc_inject_record.zi_timer;
746                 break;
747
748         case ZFS_CMD_COMPAT_V15:
749                 zc_c = (void *)addr;
750
751                 /* zc */
752                 strlcpy(zc_c->zc_name, zc->zc_name, MAXPATHLEN);
753                 strlcpy(zc_c->zc_value, zc->zc_value, MAXPATHLEN);
754                 strlcpy(zc_c->zc_string, zc->zc_string, MAXPATHLEN);
755                 zc_c->zc_guid = zc->zc_guid;
756                 zc_c->zc_nvlist_conf = zc->zc_nvlist_conf;
757                 zc_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
758                 zc_c->zc_nvlist_src = zc->zc_nvlist_src;
759                 zc_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
760                 zc_c->zc_nvlist_dst = zc->zc_nvlist_dst;
761                 zc_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
762                 zc_c->zc_cookie = zc->zc_cookie;
763                 zc_c->zc_objset_type = zc->zc_objset_type;
764                 zc_c->zc_perm_action = zc->zc_perm_action;
765                 zc_c->zc_history = zc->zc_history;
766                 zc_c->zc_history_len = zc->zc_history_len;
767                 zc_c->zc_history_offset = zc->zc_history_offset;
768                 zc_c->zc_obj = zc->zc_obj;
769                 zc_c->zc_share = zc->zc_share;
770                 zc_c->zc_jailid = zc->zc_jailid;
771                 zc_c->zc_objset_stats = zc->zc_objset_stats;
772                 zc_c->zc_begin_record = zc->zc_begin_record.drr_u.drr_begin;
773
774                 /* zc_inject_record */
775                 zc_c->zc_inject_record.zi_objset =
776                     zc->zc_inject_record.zi_objset;
777                 zc_c->zc_inject_record.zi_object =
778                     zc->zc_inject_record.zi_object;
779                 zc_c->zc_inject_record.zi_start =
780                     zc->zc_inject_record.zi_start;
781                 zc_c->zc_inject_record.zi_end =
782                     zc->zc_inject_record.zi_end;
783                 zc_c->zc_inject_record.zi_guid =
784                     zc->zc_inject_record.zi_guid;
785                 zc_c->zc_inject_record.zi_level =
786                     zc->zc_inject_record.zi_level;
787                 zc_c->zc_inject_record.zi_error =
788                     zc->zc_inject_record.zi_error;
789                 zc_c->zc_inject_record.zi_type =
790                     zc->zc_inject_record.zi_type;
791                 zc_c->zc_inject_record.zi_freq =
792                     zc->zc_inject_record.zi_freq;
793                 zc_c->zc_inject_record.zi_failfast =
794                     zc->zc_inject_record.zi_failfast;
795
796                 break;
797         }
798 }
799
800 static int
801 zfs_ioctl_compat_get_nvlist(uint64_t nvl, size_t size, int iflag,
802     nvlist_t **nvp)
803 {
804         char *packed;
805         int error;
806         nvlist_t *list = NULL;
807
808         /*
809          * Read in and unpack the user-supplied nvlist.
810          */
811         if (size == 0)
812                 return (EINVAL);
813
814 #ifdef _KERNEL
815         packed = kmem_alloc(size, KM_SLEEP);
816         if ((error = ddi_copyin((void *)(uintptr_t)nvl, packed, size,
817             iflag)) != 0) {
818                 kmem_free(packed, size);
819                 return (error);
820         }
821 #else
822         packed = (void *)(uintptr_t)nvl;
823 #endif
824
825         error = nvlist_unpack(packed, size, &list, 0);
826
827 #ifdef _KERNEL
828         kmem_free(packed, size);
829 #endif
830
831         if (error != 0)
832                 return (error);
833
834         *nvp = list;
835         return (0);
836 }
837
838 static int
839 zfs_ioctl_compat_put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
840 {
841         char *packed = NULL;
842         int error = 0;
843         size_t size;
844
845         VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0);
846
847 #ifdef _KERNEL
848         packed = kmem_alloc(size, KM_SLEEP);
849         VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
850             KM_SLEEP) == 0);
851
852         if (ddi_copyout(packed,
853             (void *)(uintptr_t)zc->zc_nvlist_dst, size, zc->zc_iflags) != 0)
854                 error = EFAULT;
855         kmem_free(packed, size);
856 #else
857         packed = (void *)(uintptr_t)zc->zc_nvlist_dst;
858         VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
859             0) == 0);
860 #endif
861
862         zc->zc_nvlist_dst_size = size;
863         return (error);
864 }
865
866 static void
867 zfs_ioctl_compat_fix_stats_nvlist(nvlist_t *nvl)
868 {
869         nvlist_t **child;
870         nvlist_t *nvroot = NULL;
871         vdev_stat_t *vs;
872         uint_t c, children, nelem;
873
874         if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_CHILDREN,
875             &child, &children) == 0) {
876                 for (c = 0; c < children; c++) {
877                         zfs_ioctl_compat_fix_stats_nvlist(child[c]);
878                 }
879         }
880
881         if (nvlist_lookup_nvlist(nvl, ZPOOL_CONFIG_VDEV_TREE,
882             &nvroot) == 0)
883                 zfs_ioctl_compat_fix_stats_nvlist(nvroot);
884 #ifdef _KERNEL
885         if ((nvlist_lookup_uint64_array(nvl, ZPOOL_CONFIG_VDEV_STATS,
886 #else
887         if ((nvlist_lookup_uint64_array(nvl, "stats",
888 #endif
889
890             (uint64_t **)&vs, &nelem) == 0)) {
891                 nvlist_add_uint64_array(nvl,
892 #ifdef _KERNEL
893                     "stats",
894 #else
895                     ZPOOL_CONFIG_VDEV_STATS,
896 #endif
897                     (uint64_t *)vs, nelem);
898 #ifdef _KERNEL
899                 nvlist_remove(nvl, ZPOOL_CONFIG_VDEV_STATS,
900 #else
901                 nvlist_remove(nvl, "stats",
902 #endif
903                     DATA_TYPE_UINT64_ARRAY);
904         }
905 }
906
907 static int
908 zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int nc)
909 {
910         nvlist_t *nv, *nvp = NULL;
911         nvpair_t *elem;
912         int error;
913
914         if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst,
915             zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
916                 return (error);
917
918         if (nc == 5) { /* ZFS_IOC_POOL_STATS */
919                 elem = NULL;
920                 while ((elem = nvlist_next_nvpair(nv, elem)) != NULL) {
921                         if (nvpair_value_nvlist(elem, &nvp) == 0)
922                                 zfs_ioctl_compat_fix_stats_nvlist(nvp);
923                 }
924                 elem = NULL;
925         } else
926                 zfs_ioctl_compat_fix_stats_nvlist(nv);
927
928         error = zfs_ioctl_compat_put_nvlist(zc, nv);
929
930         nvlist_free(nv);
931
932         return (error);
933 }
934
935 static int
936 zfs_ioctl_compat_pool_get_props(zfs_cmd_t *zc)
937 {
938         nvlist_t *nv, *nva = NULL;
939         int error;
940
941         if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst,
942             zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
943                 return (error);
944
945 #ifdef _KERNEL
946         if (nvlist_lookup_nvlist(nv, "allocated", &nva) == 0) {
947                 nvlist_add_nvlist(nv, "used", nva);
948                 nvlist_remove(nv, "allocated", DATA_TYPE_NVLIST);
949         }
950
951         if (nvlist_lookup_nvlist(nv, "free", &nva) == 0) {
952                 nvlist_add_nvlist(nv, "available", nva);
953                 nvlist_remove(nv, "free", DATA_TYPE_NVLIST);
954         }
955 #else
956         if (nvlist_lookup_nvlist(nv, "used", &nva) == 0) {
957                 nvlist_add_nvlist(nv, "allocated", nva);
958                 nvlist_remove(nv, "used", DATA_TYPE_NVLIST);
959         }
960
961         if (nvlist_lookup_nvlist(nv, "available", &nva) == 0) {
962                 nvlist_add_nvlist(nv, "free", nva);
963                 nvlist_remove(nv, "available", DATA_TYPE_NVLIST);
964         }
965 #endif
966
967         error = zfs_ioctl_compat_put_nvlist(zc, nv);
968
969         nvlist_free(nv);
970
971         return (error);
972 }
973
974 #ifndef _KERNEL
975 int
976 zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag)
977 {
978         int nc, ret;
979         void *zc_c;
980         unsigned long ncmd;
981         zfs_iocparm_t zp;
982
983         switch (cflag) {
984         case ZFS_CMD_COMPAT_NONE:
985                 ncmd = _IOWR('Z', request, struct zfs_iocparm);
986                 zp.zfs_cmd = (uint64_t)zc;
987                 zp.zfs_cmd_size = sizeof(zfs_cmd_t);
988                 zp.zfs_ioctl_version = ZFS_IOCVER_CURRENT;
989                 return (ioctl(fd, ncmd, &zp));
990         case ZFS_CMD_COMPAT_RESUME:
991                 ncmd = _IOWR('Z', request, struct zfs_iocparm);
992                 zp.zfs_cmd = (uint64_t)zc;
993                 zp.zfs_cmd_size = sizeof(zfs_cmd_resume_t);
994                 zp.zfs_ioctl_version = ZFS_IOCVER_RESUME;
995                 return (ioctl(fd, ncmd, &zp));
996         case ZFS_CMD_COMPAT_EDBP:
997                 ncmd = _IOWR('Z', request, struct zfs_iocparm);
998                 zp.zfs_cmd = (uint64_t)zc;
999                 zp.zfs_cmd_size = sizeof(zfs_cmd_edbp_t);
1000                 zp.zfs_ioctl_version = ZFS_IOCVER_EDBP;
1001                 return (ioctl(fd, ncmd, &zp));
1002         case ZFS_CMD_COMPAT_ZCMD:
1003                 ncmd = _IOWR('Z', request, struct zfs_iocparm);
1004                 zp.zfs_cmd = (uint64_t)zc;
1005                 zp.zfs_cmd_size = sizeof(zfs_cmd_zcmd_t);
1006                 zp.zfs_ioctl_version = ZFS_IOCVER_ZCMD;
1007                 return (ioctl(fd, ncmd, &zp));
1008         case ZFS_CMD_COMPAT_LZC:
1009                 ncmd = _IOWR('Z', request, struct zfs_cmd);
1010                 return (ioctl(fd, ncmd, zc));
1011         case ZFS_CMD_COMPAT_DEADMAN:
1012                 zc_c = malloc(sizeof(zfs_cmd_deadman_t));
1013                 ncmd = _IOWR('Z', request, struct zfs_cmd_deadman);
1014                 break;
1015         case ZFS_CMD_COMPAT_V28:
1016                 zc_c = malloc(sizeof(zfs_cmd_v28_t));
1017                 ncmd = _IOWR('Z', request, struct zfs_cmd_v28);
1018                 break;
1019         case ZFS_CMD_COMPAT_V15:
1020                 nc = zfs_ioctl_v28_to_v15[request];
1021                 zc_c = malloc(sizeof(zfs_cmd_v15_t));
1022                 ncmd = _IOWR('Z', nc, struct zfs_cmd_v15);
1023                 break;
1024         default:
1025                 return (EINVAL);
1026         }
1027
1028         if (ZFS_IOCREQ(ncmd) == ZFS_IOC_COMPAT_FAIL)
1029                 return (ENOTSUP);
1030
1031         zfs_cmd_compat_put(zc, (caddr_t)zc_c, request, cflag);
1032
1033         ret = ioctl(fd, ncmd, zc_c);
1034         if (cflag == ZFS_CMD_COMPAT_V15 &&
1035             nc == ZFS_IOC_POOL_IMPORT)
1036                 ret = ioctl(fd, _IOWR('Z', ZFS_IOC_POOL_CONFIGS,
1037                     struct zfs_cmd_v15), zc_c);
1038         zfs_cmd_compat_get(zc, (caddr_t)zc_c, cflag);
1039         free(zc_c);
1040
1041         if (cflag == ZFS_CMD_COMPAT_V15) {
1042                 switch (nc) {
1043                 case ZFS_IOC_POOL_IMPORT:
1044                 case ZFS_IOC_POOL_CONFIGS:
1045                 case ZFS_IOC_POOL_STATS:
1046                 case ZFS_IOC_POOL_TRYIMPORT:
1047                         zfs_ioctl_compat_fix_stats(zc, nc);
1048                         break;
1049                 case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
1050                         zfs_ioctl_compat_pool_get_props(zc);
1051                         break;
1052                 }
1053         }
1054
1055         return (ret);
1056 }
1057 #else /* _KERNEL */
1058 int
1059 zfs_ioctl_compat_pre(zfs_cmd_t *zc, int *vec, const int cflag)
1060 {
1061         int error = 0;
1062
1063         /* are we creating a clone? */
1064         if (*vec == ZFS_IOC_CREATE && zc->zc_value[0] != '\0')
1065                 *vec = ZFS_IOC_CLONE;
1066
1067         if (cflag == ZFS_CMD_COMPAT_V15) {
1068                 switch (*vec) {
1069
1070                 case 7: /* ZFS_IOC_POOL_SCRUB (v15) */
1071                         zc->zc_cookie = POOL_SCAN_SCRUB;
1072                         break;
1073                 }
1074         }
1075
1076         return (error);
1077 }
1078
1079 void
1080 zfs_ioctl_compat_post(zfs_cmd_t *zc, int vec, const int cflag)
1081 {
1082         if (cflag == ZFS_CMD_COMPAT_V15) {
1083                 switch (vec) {
1084                 case ZFS_IOC_POOL_CONFIGS:
1085                 case ZFS_IOC_POOL_STATS:
1086                 case ZFS_IOC_POOL_TRYIMPORT:
1087                         zfs_ioctl_compat_fix_stats(zc, vec);
1088                         break;
1089                 case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
1090                         zfs_ioctl_compat_pool_get_props(zc);
1091                         break;
1092                 }
1093         }
1094 }
1095
1096 nvlist_t *
1097 zfs_ioctl_compat_innvl(zfs_cmd_t *zc, nvlist_t * innvl, const int vec,
1098     const int cflag)
1099 {
1100         nvlist_t *nvl, *tmpnvl, *hnvl;
1101         nvpair_t *elem;
1102         char *poolname, *snapname;
1103         int err;
1104
1105         if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC ||
1106             cflag == ZFS_CMD_COMPAT_ZCMD || cflag == ZFS_CMD_COMPAT_EDBP ||
1107             cflag == ZFS_CMD_COMPAT_RESUME)
1108                 goto out;
1109
1110         switch (vec) {
1111         case ZFS_IOC_CREATE:
1112                 nvl = fnvlist_alloc();
1113                 fnvlist_add_int32(nvl, "type", zc->zc_objset_type);
1114                 if (innvl != NULL) {
1115                         fnvlist_add_nvlist(nvl, "props", innvl);
1116                         nvlist_free(innvl);
1117                 }
1118                 return (nvl);
1119         break;
1120         case ZFS_IOC_CLONE:
1121                 nvl = fnvlist_alloc();
1122                 fnvlist_add_string(nvl, "origin", zc->zc_value);
1123                 if (innvl != NULL) {
1124                         fnvlist_add_nvlist(nvl, "props", innvl);
1125                         nvlist_free(innvl);
1126                 }
1127                 return (nvl);
1128         break;
1129         case ZFS_IOC_SNAPSHOT:
1130                 if (innvl == NULL)
1131                         goto out;
1132                 nvl = fnvlist_alloc();
1133                 fnvlist_add_nvlist(nvl, "props", innvl);
1134                 tmpnvl = fnvlist_alloc();
1135                 snapname = kmem_asprintf("%s@%s", zc->zc_name, zc->zc_value);
1136                 fnvlist_add_boolean(tmpnvl, snapname);
1137                 kmem_free(snapname, strlen(snapname + 1));
1138                 /* check if we are doing a recursive snapshot */
1139                 if (zc->zc_cookie)
1140                         dmu_get_recursive_snaps_nvl(zc->zc_name, zc->zc_value,
1141                             tmpnvl);
1142                 fnvlist_add_nvlist(nvl, "snaps", tmpnvl);
1143                 fnvlist_free(tmpnvl);
1144                 nvlist_free(innvl);
1145                 /* strip dataset part from zc->zc_name */
1146                 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
1147                 return (nvl);
1148         break;
1149         case ZFS_IOC_SPACE_SNAPS:
1150                 nvl = fnvlist_alloc();
1151                 fnvlist_add_string(nvl, "firstsnap", zc->zc_value);
1152                 if (innvl != NULL)
1153                         nvlist_free(innvl);
1154                 return (nvl);
1155         break;
1156         case ZFS_IOC_DESTROY_SNAPS:
1157                 if (innvl == NULL && cflag == ZFS_CMD_COMPAT_DEADMAN)
1158                         goto out;
1159                 nvl = fnvlist_alloc();
1160                 if (innvl != NULL) {
1161                         fnvlist_add_nvlist(nvl, "snaps", innvl);
1162                 } else {
1163                         /*
1164                          * We are probably called by even older binaries,
1165                          * allocate and populate nvlist with recursive
1166                          * snapshots
1167                          */
1168                         if (zfs_component_namecheck(zc->zc_value, NULL,
1169                             NULL) == 0) {
1170                                 tmpnvl = fnvlist_alloc();
1171                                 if (dmu_get_recursive_snaps_nvl(zc->zc_name,
1172                                     zc->zc_value, tmpnvl) == 0)
1173                                         fnvlist_add_nvlist(nvl, "snaps",
1174                                             tmpnvl);
1175                                 nvlist_free(tmpnvl);
1176                         }
1177                 }
1178                 if (innvl != NULL)
1179                         nvlist_free(innvl);
1180                 /* strip dataset part from zc->zc_name */
1181                 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
1182                 return (nvl);
1183         break;
1184         case ZFS_IOC_HOLD:
1185                 nvl = fnvlist_alloc();
1186                 tmpnvl = fnvlist_alloc();
1187                 if (zc->zc_cleanup_fd != -1)
1188                         fnvlist_add_int32(nvl, "cleanup_fd",
1189                             (int32_t)zc->zc_cleanup_fd);
1190                 if (zc->zc_cookie) {
1191                         hnvl = fnvlist_alloc();
1192                         if (dmu_get_recursive_snaps_nvl(zc->zc_name,
1193                             zc->zc_value, hnvl) == 0) {
1194                                 elem = NULL;
1195                                 while ((elem = nvlist_next_nvpair(hnvl,
1196                                     elem)) != NULL) {
1197                                         nvlist_add_string(tmpnvl,
1198                                             nvpair_name(elem), zc->zc_string);
1199                                 }
1200                         }
1201                         nvlist_free(hnvl);
1202                 } else {
1203                         snapname = kmem_asprintf("%s@%s", zc->zc_name,
1204                             zc->zc_value);
1205                         nvlist_add_string(tmpnvl, snapname, zc->zc_string);
1206                         kmem_free(snapname, strlen(snapname + 1));
1207                 }
1208                 fnvlist_add_nvlist(nvl, "holds", tmpnvl);
1209                 nvlist_free(tmpnvl);
1210                 if (innvl != NULL)
1211                         nvlist_free(innvl);
1212                 /* strip dataset part from zc->zc_name */
1213                 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
1214                 return (nvl);
1215         break;
1216         case ZFS_IOC_RELEASE:
1217                 nvl = fnvlist_alloc();
1218                 tmpnvl = fnvlist_alloc();
1219                 if (zc->zc_cookie) {
1220                         hnvl = fnvlist_alloc();
1221                         if (dmu_get_recursive_snaps_nvl(zc->zc_name,
1222                             zc->zc_value, hnvl) == 0) {
1223                                 elem = NULL;
1224                                 while ((elem = nvlist_next_nvpair(hnvl,
1225                                     elem)) != NULL) {
1226                                         fnvlist_add_boolean(tmpnvl,
1227                                             zc->zc_string);
1228                                         fnvlist_add_nvlist(nvl,
1229                                             nvpair_name(elem), tmpnvl);
1230                                 }
1231                         }
1232                         nvlist_free(hnvl);
1233                 } else {
1234                         snapname = kmem_asprintf("%s@%s", zc->zc_name,
1235                             zc->zc_value);
1236                         fnvlist_add_boolean(tmpnvl, zc->zc_string);
1237                         fnvlist_add_nvlist(nvl, snapname, tmpnvl);
1238                         kmem_free(snapname, strlen(snapname + 1));
1239                 }
1240                 nvlist_free(tmpnvl);
1241                 if (innvl != NULL)
1242                         nvlist_free(innvl);
1243                 /* strip dataset part from zc->zc_name */
1244                 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
1245                 return (nvl);
1246         break;
1247         }
1248 out:
1249         return (innvl);
1250 }
1251
1252 nvlist_t *
1253 zfs_ioctl_compat_outnvl(zfs_cmd_t *zc, nvlist_t * outnvl, const int vec,
1254     const int cflag)
1255 {
1256         nvlist_t *tmpnvl;
1257
1258         if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC ||
1259             cflag == ZFS_CMD_COMPAT_ZCMD || cflag == ZFS_CMD_COMPAT_EDBP ||
1260             cflag == ZFS_CMD_COMPAT_RESUME)
1261                 return (outnvl);
1262
1263         switch (vec) {
1264         case ZFS_IOC_SPACE_SNAPS:
1265                 (void) nvlist_lookup_uint64(outnvl, "used", &zc->zc_cookie);
1266                 (void) nvlist_lookup_uint64(outnvl, "compressed",
1267                     &zc->zc_objset_type);
1268                 (void) nvlist_lookup_uint64(outnvl, "uncompressed",
1269                     &zc->zc_perm_action);
1270                 nvlist_free(outnvl);
1271                 /* return empty outnvl */
1272                 tmpnvl = fnvlist_alloc();
1273                 return (tmpnvl);
1274         break;
1275         case ZFS_IOC_CREATE:
1276         case ZFS_IOC_CLONE:
1277         case ZFS_IOC_HOLD:
1278         case ZFS_IOC_RELEASE:
1279                 nvlist_free(outnvl);
1280                 /* return empty outnvl */
1281                 tmpnvl = fnvlist_alloc();
1282                 return (tmpnvl);
1283         break;
1284         }
1285
1286         return (outnvl);
1287 }
1288 #endif /* KERNEL */