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