]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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
57         switch (cflag) {
58         case ZFS_CMD_COMPAT_ZCMD:
59                 zcmd_c = (void *)addr;
60                 /* zc */
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);
64
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);
71                 ZCMD_COPY(zc_pad2);
72                 ZCMD_COPY(zc_history);
73                 ZCMD_COPY(zc_guid);
74                 ZCMD_COPY(zc_nvlist_conf);
75                 ZCMD_COPY(zc_nvlist_conf_size);
76                 ZCMD_COPY(zc_cookie);
77                 ZCMD_COPY(zc_objset_type);
78                 ZCMD_COPY(zc_perm_action);
79                 ZCMD_COPY(zc_history_len);
80                 ZCMD_COPY(zc_history_offset);
81                 ZCMD_COPY(zc_obj);
82                 ZCMD_COPY(zc_iflags);
83                 ZCMD_COPY(zc_share);
84                 ZCMD_COPY(zc_jailid);
85                 ZCMD_COPY(zc_objset_stats);
86
87                 /*
88                  * zc_begin_record, zc_inject_record didn't change in embedeed-data
89                  * block pointers
90                  *
91                  * TODO: CTASSERT?
92                  */
93                 ZCMD_COPY(zc_begin_record);
94                 ZCMD_COPY(zc_inject_record);
95
96                 /* boolean_t -> uint32_t */
97                 zc->zc_defer_destroy = (uint32_t)(zcmd_c->zc_defer_destroy);
98                 zc->zc_flags = 0;
99
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);
107                 ZCMD_COPY(zc_stat);
108 #undef ZCMD_COPY
109
110                 break;
111
112         case ZFS_CMD_COMPAT_DEADMAN:
113                 zcdm_c = (void *)addr;
114                 /* zc */
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;
147
148                 /* zc_inject_record doesn't change in libzfs_core */
149                 zcdm_c->zc_inject_record = zc->zc_inject_record;
150
151                 /* we always assume zc_nvlist_dst_filled is true */
152                 zc->zc_nvlist_dst_filled = B_TRUE;
153                 break;
154
155         case ZFS_CMD_COMPAT_V28:
156                 zc28_c = (void *)addr;
157
158                 /* zc */
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;
191
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;
223                 break;
224
225         case ZFS_CMD_COMPAT_V15:
226                 zc_c = (void *)addr;
227
228                 /* zc */
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;
250
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;
272                 break;
273         }
274 }
275
276 void
277 zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_t addr, const int request,
278     const int cflag)
279 {
280         zfs_cmd_v15_t *zc_c;
281         zfs_cmd_v28_t *zc28_c;
282         zfs_cmd_deadman_t *zcdm_c;
283         zfs_cmd_zcmd_t *zcmd_c;
284
285         switch (cflag) {
286         case ZFS_CMD_COMPAT_ZCMD:
287                 zcmd_c = (void *)addr;
288                 /* zc */
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);
292
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);
299                 ZCMD_COPY(zc_pad2);
300                 ZCMD_COPY(zc_history);
301                 ZCMD_COPY(zc_guid);
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);
309                 ZCMD_COPY(zc_obj);
310                 ZCMD_COPY(zc_iflags);
311                 ZCMD_COPY(zc_share);
312                 ZCMD_COPY(zc_jailid);
313                 ZCMD_COPY(zc_objset_stats);
314
315                 /*
316                  * zc_begin_record, zc_inject_record didn't change in embedeed-data
317                  * block pointers
318                  *
319                  * TODO: CTASSERT?
320                  */
321                 ZCMD_COPY(zc_begin_record);
322                 ZCMD_COPY(zc_inject_record);
323
324                 /* boolean_t -> uint32_t */
325                 zcmd_c->zc_defer_destroy = (uint32_t)(zc->zc_defer_destroy);
326                 zcmd_c->zc_temphold = 0;
327
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);
335                 ZCMD_COPY(zc_stat);
336 #undef ZCMD_COPY
337
338                 break;
339
340         case ZFS_CMD_COMPAT_DEADMAN:
341                 zcdm_c = (void *)addr;
342
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;
375
376                 /* zc_inject_record doesn't change in libzfs_core */
377                 zc->zc_inject_record = zcdm_c->zc_inject_record;
378 #ifndef _KERNEL
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);
383 #endif
384                 break;
385
386         case ZFS_CMD_COMPAT_V28:
387                 zc28_c = (void *)addr;
388
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;
421 #ifndef _KERNEL
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);
426 #endif
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;
456                 break;
457
458         case ZFS_CMD_COMPAT_V15:
459                 zc_c = (void *)addr;
460
461                 /* zc */
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;
483
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;
505
506                 break;
507         }
508 }
509
510 static int
511 zfs_ioctl_compat_get_nvlist(uint64_t nvl, size_t size, int iflag,
512     nvlist_t **nvp)
513 {
514         char *packed;
515         int error;
516         nvlist_t *list = NULL;
517
518         /*
519          * Read in and unpack the user-supplied nvlist.
520          */
521         if (size == 0)
522                 return (EINVAL);
523
524 #ifdef _KERNEL
525         packed = kmem_alloc(size, KM_SLEEP);
526         if ((error = ddi_copyin((void *)(uintptr_t)nvl, packed, size,
527             iflag)) != 0) {
528                 kmem_free(packed, size);
529                 return (error);
530         }
531 #else
532         packed = (void *)(uintptr_t)nvl;
533 #endif
534
535         error = nvlist_unpack(packed, size, &list, 0);
536
537 #ifdef _KERNEL
538         kmem_free(packed, size);
539 #endif
540
541         if (error != 0)
542                 return (error);
543
544         *nvp = list;
545         return (0);
546 }
547
548 static int
549 zfs_ioctl_compat_put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
550 {
551         char *packed = NULL;
552         int error = 0;
553         size_t size;
554
555         VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0);
556
557 #ifdef _KERNEL
558         packed = kmem_alloc(size, KM_SLEEP);
559         VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
560             KM_SLEEP) == 0);
561
562         if (ddi_copyout(packed,
563             (void *)(uintptr_t)zc->zc_nvlist_dst, size, zc->zc_iflags) != 0)
564                 error = EFAULT;
565         kmem_free(packed, size);
566 #else
567         packed = (void *)(uintptr_t)zc->zc_nvlist_dst;
568         VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
569             0) == 0);
570 #endif
571
572         zc->zc_nvlist_dst_size = size;
573         return (error);
574 }
575
576 static void
577 zfs_ioctl_compat_fix_stats_nvlist(nvlist_t *nvl)
578 {
579         nvlist_t **child;
580         nvlist_t *nvroot = NULL;
581         vdev_stat_t *vs;
582         uint_t c, children, nelem;
583
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]);
588                 }
589         }
590
591         if (nvlist_lookup_nvlist(nvl, ZPOOL_CONFIG_VDEV_TREE,
592             &nvroot) == 0)
593                 zfs_ioctl_compat_fix_stats_nvlist(nvroot);
594 #ifdef _KERNEL
595         if ((nvlist_lookup_uint64_array(nvl, ZPOOL_CONFIG_VDEV_STATS,
596 #else
597         if ((nvlist_lookup_uint64_array(nvl, "stats",
598 #endif
599
600             (uint64_t **)&vs, &nelem) == 0)) {
601                 nvlist_add_uint64_array(nvl,
602 #ifdef _KERNEL
603                     "stats",
604 #else
605                     ZPOOL_CONFIG_VDEV_STATS,
606 #endif
607                     (uint64_t *)vs, nelem);
608 #ifdef _KERNEL
609                 nvlist_remove(nvl, ZPOOL_CONFIG_VDEV_STATS,
610 #else
611                 nvlist_remove(nvl, "stats",
612 #endif
613                     DATA_TYPE_UINT64_ARRAY);
614         }
615 }
616
617 static int
618 zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int nc)
619 {
620         nvlist_t *nv, *nvp = NULL;
621         nvpair_t *elem;
622         int error;
623
624         if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst,
625             zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
626                 return (error);
627
628         if (nc == 5) { /* ZFS_IOC_POOL_STATS */
629                 elem = NULL;
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);
633                 }
634                 elem = NULL;
635         } else
636                 zfs_ioctl_compat_fix_stats_nvlist(nv);
637
638         error = zfs_ioctl_compat_put_nvlist(zc, nv);
639
640         nvlist_free(nv);
641
642         return (error);
643 }
644
645 static int
646 zfs_ioctl_compat_pool_get_props(zfs_cmd_t *zc)
647 {
648         nvlist_t *nv, *nva = NULL;
649         int error;
650
651         if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst,
652             zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
653                 return (error);
654
655 #ifdef _KERNEL
656         if (nvlist_lookup_nvlist(nv, "allocated", &nva) == 0) {
657                 nvlist_add_nvlist(nv, "used", nva);
658                 nvlist_remove(nv, "allocated", DATA_TYPE_NVLIST);
659         }
660
661         if (nvlist_lookup_nvlist(nv, "free", &nva) == 0) {
662                 nvlist_add_nvlist(nv, "available", nva);
663                 nvlist_remove(nv, "free", DATA_TYPE_NVLIST);
664         }
665 #else
666         if (nvlist_lookup_nvlist(nv, "used", &nva) == 0) {
667                 nvlist_add_nvlist(nv, "allocated", nva);
668                 nvlist_remove(nv, "used", DATA_TYPE_NVLIST);
669         }
670
671         if (nvlist_lookup_nvlist(nv, "available", &nva) == 0) {
672                 nvlist_add_nvlist(nv, "free", nva);
673                 nvlist_remove(nv, "available", DATA_TYPE_NVLIST);
674         }
675 #endif
676
677         error = zfs_ioctl_compat_put_nvlist(zc, nv);
678
679         nvlist_free(nv);
680
681         return (error);
682 }
683
684 #ifndef _KERNEL
685 int
686 zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag)
687 {
688         int nc, ret;
689         void *zc_c;
690         unsigned long ncmd;
691         zfs_iocparm_t zp;
692
693         switch (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_ZCMD:
701                 ncmd = _IOWR('Z', request, struct zfs_iocparm);
702                 zp.zfs_cmd = (uint64_t)zc;
703                 zp.zfs_cmd_size = sizeof(zfs_cmd_zcmd_t);
704                 zp.zfs_ioctl_version = ZFS_IOCVER_ZCMD;
705                 return (ioctl(fd, ncmd, &zp));
706         case ZFS_CMD_COMPAT_LZC:
707                 ncmd = _IOWR('Z', request, struct zfs_cmd);
708                 return (ioctl(fd, ncmd, zc));
709         case ZFS_CMD_COMPAT_DEADMAN:
710                 zc_c = malloc(sizeof(zfs_cmd_deadman_t));
711                 ncmd = _IOWR('Z', request, struct zfs_cmd_deadman);
712                 break;
713         case ZFS_CMD_COMPAT_V28:
714                 zc_c = malloc(sizeof(zfs_cmd_v28_t));
715                 ncmd = _IOWR('Z', request, struct zfs_cmd_v28);
716                 break;
717         case ZFS_CMD_COMPAT_V15:
718                 nc = zfs_ioctl_v28_to_v15[request];
719                 zc_c = malloc(sizeof(zfs_cmd_v15_t));
720                 ncmd = _IOWR('Z', nc, struct zfs_cmd_v15);
721                 break;
722         default:
723                 return (EINVAL);
724         }
725
726         if (ZFS_IOCREQ(ncmd) == ZFS_IOC_COMPAT_FAIL)
727                 return (ENOTSUP);
728
729         zfs_cmd_compat_put(zc, (caddr_t)zc_c, request, cflag);
730
731         ret = ioctl(fd, ncmd, zc_c);
732         if (cflag == ZFS_CMD_COMPAT_V15 &&
733             nc == ZFS_IOC_POOL_IMPORT)
734                 ret = ioctl(fd, _IOWR('Z', ZFS_IOC_POOL_CONFIGS,
735                     struct zfs_cmd_v15), zc_c);
736         zfs_cmd_compat_get(zc, (caddr_t)zc_c, cflag);
737         free(zc_c);
738
739         if (cflag == ZFS_CMD_COMPAT_V15) {
740                 switch (nc) {
741                 case ZFS_IOC_POOL_IMPORT:
742                 case ZFS_IOC_POOL_CONFIGS:
743                 case ZFS_IOC_POOL_STATS:
744                 case ZFS_IOC_POOL_TRYIMPORT:
745                         zfs_ioctl_compat_fix_stats(zc, nc);
746                         break;
747                 case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
748                         zfs_ioctl_compat_pool_get_props(zc);
749                         break;
750                 }
751         }
752
753         return (ret);
754 }
755 #else /* _KERNEL */
756 int
757 zfs_ioctl_compat_pre(zfs_cmd_t *zc, int *vec, const int cflag)
758 {
759         int error = 0;
760
761         /* are we creating a clone? */
762         if (*vec == ZFS_IOC_CREATE && zc->zc_value[0] != '\0')
763                 *vec = ZFS_IOC_CLONE;
764
765         if (cflag == ZFS_CMD_COMPAT_V15) {
766                 switch (*vec) {
767
768                 case 7: /* ZFS_IOC_POOL_SCRUB (v15) */
769                         zc->zc_cookie = POOL_SCAN_SCRUB;
770                         break;
771                 }
772         }
773
774         return (error);
775 }
776
777 void
778 zfs_ioctl_compat_post(zfs_cmd_t *zc, int vec, const int cflag)
779 {
780         if (cflag == ZFS_CMD_COMPAT_V15) {
781                 switch (vec) {
782                 case ZFS_IOC_POOL_CONFIGS:
783                 case ZFS_IOC_POOL_STATS:
784                 case ZFS_IOC_POOL_TRYIMPORT:
785                         zfs_ioctl_compat_fix_stats(zc, vec);
786                         break;
787                 case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
788                         zfs_ioctl_compat_pool_get_props(zc);
789                         break;
790                 }
791         }
792 }
793
794 nvlist_t *
795 zfs_ioctl_compat_innvl(zfs_cmd_t *zc, nvlist_t * innvl, const int vec,
796     const int cflag)
797 {
798         nvlist_t *nvl, *tmpnvl, *hnvl;
799         nvpair_t *elem;
800         char *poolname, *snapname;
801         int err;
802
803         if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC ||
804             cflag == ZFS_CMD_COMPAT_ZCMD)
805                 goto out;
806
807         switch (vec) {
808         case ZFS_IOC_CREATE:
809                 nvl = fnvlist_alloc();
810                 fnvlist_add_int32(nvl, "type", zc->zc_objset_type);
811                 if (innvl != NULL) {
812                         fnvlist_add_nvlist(nvl, "props", innvl);
813                         nvlist_free(innvl);
814                 }
815                 return (nvl);
816         break;
817         case ZFS_IOC_CLONE:
818                 nvl = fnvlist_alloc();
819                 fnvlist_add_string(nvl, "origin", zc->zc_value);
820                 if (innvl != NULL) {
821                         fnvlist_add_nvlist(nvl, "props", innvl);
822                         nvlist_free(innvl);
823                 }
824                 return (nvl);
825         break;
826         case ZFS_IOC_SNAPSHOT:
827                 if (innvl == NULL)
828                         goto out;
829                 nvl = fnvlist_alloc();
830                 fnvlist_add_nvlist(nvl, "props", innvl);
831                 tmpnvl = fnvlist_alloc();
832                 snapname = kmem_asprintf("%s@%s", zc->zc_name, zc->zc_value);
833                 fnvlist_add_boolean(tmpnvl, snapname);
834                 kmem_free(snapname, strlen(snapname + 1));
835                 /* check if we are doing a recursive snapshot */
836                 if (zc->zc_cookie)
837                         dmu_get_recursive_snaps_nvl(zc->zc_name, zc->zc_value,
838                             tmpnvl);
839                 fnvlist_add_nvlist(nvl, "snaps", tmpnvl);
840                 fnvlist_free(tmpnvl);
841                 nvlist_free(innvl);
842                 /* strip dataset part from zc->zc_name */
843                 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
844                 return (nvl);
845         break;
846         case ZFS_IOC_SPACE_SNAPS:
847                 nvl = fnvlist_alloc();
848                 fnvlist_add_string(nvl, "firstsnap", zc->zc_value);
849                 if (innvl != NULL)
850                         nvlist_free(innvl);
851                 return (nvl);
852         break;
853         case ZFS_IOC_DESTROY_SNAPS:
854                 if (innvl == NULL && cflag == ZFS_CMD_COMPAT_DEADMAN)
855                         goto out;
856                 nvl = fnvlist_alloc();
857                 if (innvl != NULL) {
858                         fnvlist_add_nvlist(nvl, "snaps", innvl);
859                 } else {
860                         /*
861                          * We are probably called by even older binaries,
862                          * allocate and populate nvlist with recursive
863                          * snapshots
864                          */
865                         if (zfs_component_namecheck(zc->zc_value, NULL,
866                             NULL) == 0) {
867                                 tmpnvl = fnvlist_alloc();
868                                 if (dmu_get_recursive_snaps_nvl(zc->zc_name,
869                                     zc->zc_value, tmpnvl) == 0)
870                                         fnvlist_add_nvlist(nvl, "snaps",
871                                             tmpnvl);
872                                 nvlist_free(tmpnvl);
873                         }
874                 }
875                 if (innvl != NULL)
876                         nvlist_free(innvl);
877                 /* strip dataset part from zc->zc_name */
878                 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
879                 return (nvl);
880         break;
881         case ZFS_IOC_HOLD:
882                 nvl = fnvlist_alloc();
883                 tmpnvl = fnvlist_alloc();
884                 if (zc->zc_cleanup_fd != -1)
885                         fnvlist_add_int32(nvl, "cleanup_fd",
886                             (int32_t)zc->zc_cleanup_fd);
887                 if (zc->zc_cookie) {
888                         hnvl = fnvlist_alloc();
889                         if (dmu_get_recursive_snaps_nvl(zc->zc_name,
890                             zc->zc_value, hnvl) == 0) {
891                                 elem = NULL;
892                                 while ((elem = nvlist_next_nvpair(hnvl,
893                                     elem)) != NULL) {
894                                         nvlist_add_string(tmpnvl,
895                                             nvpair_name(elem), zc->zc_string);
896                                 }
897                         }
898                         nvlist_free(hnvl);
899                 } else {
900                         snapname = kmem_asprintf("%s@%s", zc->zc_name,
901                             zc->zc_value);
902                         nvlist_add_string(tmpnvl, snapname, zc->zc_string);
903                         kmem_free(snapname, strlen(snapname + 1));
904                 }
905                 fnvlist_add_nvlist(nvl, "holds", tmpnvl);
906                 nvlist_free(tmpnvl);
907                 if (innvl != NULL)
908                         nvlist_free(innvl);
909                 /* strip dataset part from zc->zc_name */
910                 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
911                 return (nvl);
912         break;
913         case ZFS_IOC_RELEASE:
914                 nvl = fnvlist_alloc();
915                 tmpnvl = fnvlist_alloc();
916                 if (zc->zc_cookie) {
917                         hnvl = fnvlist_alloc();
918                         if (dmu_get_recursive_snaps_nvl(zc->zc_name,
919                             zc->zc_value, hnvl) == 0) {
920                                 elem = NULL;
921                                 while ((elem = nvlist_next_nvpair(hnvl,
922                                     elem)) != NULL) {
923                                         fnvlist_add_boolean(tmpnvl,
924                                             zc->zc_string);
925                                         fnvlist_add_nvlist(nvl,
926                                             nvpair_name(elem), tmpnvl);
927                                 }
928                         }
929                         nvlist_free(hnvl);
930                 } else {
931                         snapname = kmem_asprintf("%s@%s", zc->zc_name,
932                             zc->zc_value);
933                         fnvlist_add_boolean(tmpnvl, zc->zc_string);
934                         fnvlist_add_nvlist(nvl, snapname, tmpnvl);
935                         kmem_free(snapname, strlen(snapname + 1));
936                 }
937                 nvlist_free(tmpnvl);
938                 if (innvl != NULL)
939                         nvlist_free(innvl);
940                 /* strip dataset part from zc->zc_name */
941                 zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
942                 return (nvl);
943         break;
944         }
945 out:
946         return (innvl);
947 }
948
949 nvlist_t *
950 zfs_ioctl_compat_outnvl(zfs_cmd_t *zc, nvlist_t * outnvl, const int vec,
951     const int cflag)
952 {
953         nvlist_t *tmpnvl;
954
955         if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC ||
956             cflag == ZFS_CMD_COMPAT_ZCMD)
957                 return (outnvl);
958
959         switch (vec) {
960         case ZFS_IOC_SPACE_SNAPS:
961                 (void) nvlist_lookup_uint64(outnvl, "used", &zc->zc_cookie);
962                 (void) nvlist_lookup_uint64(outnvl, "compressed",
963                     &zc->zc_objset_type);
964                 (void) nvlist_lookup_uint64(outnvl, "uncompressed",
965                     &zc->zc_perm_action);
966                 nvlist_free(outnvl);
967                 /* return empty outnvl */
968                 tmpnvl = fnvlist_alloc();
969                 return (tmpnvl);
970         break;
971         case ZFS_IOC_CREATE:
972         case ZFS_IOC_CLONE:
973         case ZFS_IOC_HOLD:
974         case ZFS_IOC_RELEASE:
975                 nvlist_free(outnvl);
976                 /* return empty outnvl */
977                 tmpnvl = fnvlist_alloc();
978                 return (tmpnvl);
979         break;
980         }
981
982         return (outnvl);
983 }
984 #endif /* KERNEL */