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