zfs_ioctl_compat.c revision 297108
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 40static int zfs_version_ioctl = ZFS_IOCVER_CURRENT; 41SYSCTL_DECL(_vfs_zfs_version); 42SYSCTL_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 */ 49void 50zfs_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 427void 428zfs_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 800static int 801zfs_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 838static int 839zfs_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 866static void 867zfs_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 907static int 908zfs_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 935static int 936zfs_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 975int 976zcmd_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 */ 1058int 1059zfs_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 1079void 1080zfs_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 1096nvlist_t * 1097zfs_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 } 1248out: 1249 return (innvl); 1250} 1251 1252nvlist_t * 1253zfs_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 */ 1289