1219089Spjd/* 2219089Spjd * CDDL HEADER START 3219089Spjd * 4219089Spjd * The contents of this file are subject to the terms of the 5219089Spjd * Common Development and Distribution License (the "License"). 6219089Spjd * You may not use this file except in compliance with the License. 7219089Spjd * 8219089Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9219089Spjd * or http://www.opensolaris.org/os/licensing. 10219089Spjd * See the License for the specific language governing permissions 11219089Spjd * and limitations under the License. 12219089Spjd * 13219089Spjd * When distributing Covered Code, include this CDDL HEADER in each 14219089Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15219089Spjd * If applicable, add the following below this CDDL HEADER, with the 16219089Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17219089Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18219089Spjd * 19219089Spjd * CDDL HEADER END 20219089Spjd */ 21219089Spjd/* 22268649Sdelphij * Copyright 2013 Xin Li <delphij@FreeBSD.org>. All rights reserved. 23247540Smm * Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved. 24220447Smm * Portions Copyright 2005, 2010, Oracle and/or its affiliates. 25220447Smm * All rights reserved. 26219089Spjd * Use is subject to license terms. 27219089Spjd */ 28219089Spjd 29219089Spjd#include <sys/types.h> 30219089Spjd#include <sys/param.h> 31219089Spjd#include <sys/cred.h> 32219089Spjd#include <sys/dmu.h> 33219089Spjd#include <sys/zio.h> 34219089Spjd#include <sys/nvpair.h> 35219089Spjd#include <sys/dsl_deleg.h> 36219089Spjd#include <sys/zfs_ioctl.h> 37248571Smm#include "zfs_namecheck.h" 38219089Spjd#include "zfs_ioctl_compat.h" 39219089Spjd 40247540Smmstatic int zfs_version_ioctl = ZFS_IOCVER_CURRENT; 41247540SmmSYSCTL_DECL(_vfs_zfs_version); 42247540SmmSYSCTL_INT(_vfs_zfs_version, OID_AUTO, ioctl, CTLFLAG_RD, &zfs_version_ioctl, 43247540Smm 0, "ZFS_IOCTL_VERSION"); 44247540Smm 45219089Spjd/* 46247540Smm * FreeBSD zfs_cmd compatibility with older binaries 47219089Spjd * appropriately remap/extend the zfs_cmd_t structure 48219089Spjd */ 49219089Spjdvoid 50219089Spjdzfs_cmd_compat_get(zfs_cmd_t *zc, caddr_t addr, const int cflag) 51219089Spjd{ 52219089Spjd zfs_cmd_v15_t *zc_c; 53247540Smm zfs_cmd_v28_t *zc28_c; 54248571Smm zfs_cmd_deadman_t *zcdm_c; 55268649Sdelphij zfs_cmd_zcmd_t *zcmd_c; 56219089Spjd 57247540Smm switch (cflag) { 58268649Sdelphij case ZFS_CMD_COMPAT_ZCMD: 59268649Sdelphij zcmd_c = (void *)addr; 60268649Sdelphij /* zc */ 61268649Sdelphij strlcpy(zc->zc_name, zcmd_c->zc_name, MAXPATHLEN); 62268649Sdelphij strlcpy(zc->zc_value, zcmd_c->zc_value, MAXPATHLEN * 2); 63268649Sdelphij strlcpy(zc->zc_string, zcmd_c->zc_string, MAXPATHLEN); 64268649Sdelphij 65268649Sdelphij#define ZCMD_COPY(field) zc->field = zcmd_c->field 66268649Sdelphij ZCMD_COPY(zc_nvlist_src); 67268649Sdelphij ZCMD_COPY(zc_nvlist_src_size); 68268649Sdelphij ZCMD_COPY(zc_nvlist_dst); 69268649Sdelphij ZCMD_COPY(zc_nvlist_dst_size); 70268649Sdelphij ZCMD_COPY(zc_nvlist_dst_filled); 71268649Sdelphij ZCMD_COPY(zc_pad2); 72268649Sdelphij ZCMD_COPY(zc_history); 73268649Sdelphij ZCMD_COPY(zc_guid); 74268649Sdelphij ZCMD_COPY(zc_nvlist_conf); 75268649Sdelphij ZCMD_COPY(zc_nvlist_conf_size); 76268649Sdelphij ZCMD_COPY(zc_cookie); 77268649Sdelphij ZCMD_COPY(zc_objset_type); 78268649Sdelphij ZCMD_COPY(zc_perm_action); 79268649Sdelphij ZCMD_COPY(zc_history_len); 80268649Sdelphij ZCMD_COPY(zc_history_offset); 81268649Sdelphij ZCMD_COPY(zc_obj); 82268649Sdelphij ZCMD_COPY(zc_iflags); 83268649Sdelphij ZCMD_COPY(zc_share); 84268649Sdelphij ZCMD_COPY(zc_jailid); 85268649Sdelphij ZCMD_COPY(zc_objset_stats); 86268649Sdelphij 87268649Sdelphij /* 88268649Sdelphij * zc_begin_record, zc_inject_record didn't change in embedeed-data 89268649Sdelphij * block pointers 90268649Sdelphij * 91268649Sdelphij * TODO: CTASSERT? 92268649Sdelphij */ 93268649Sdelphij ZCMD_COPY(zc_begin_record); 94268649Sdelphij ZCMD_COPY(zc_inject_record); 95268649Sdelphij 96268649Sdelphij /* boolean_t -> uint32_t */ 97268649Sdelphij zc->zc_defer_destroy = (uint32_t)(zcmd_c->zc_defer_destroy); 98268649Sdelphij zc->zc_flags = 0; 99268649Sdelphij 100268649Sdelphij ZCMD_COPY(zc_action_handle); 101268649Sdelphij ZCMD_COPY(zc_cleanup_fd); 102268649Sdelphij ZCMD_COPY(zc_simple); 103268649Sdelphij bcopy(zcmd_c->zc_pad, zc->zc_pad, sizeof(zc->zc_pad)); 104268649Sdelphij ZCMD_COPY(zc_sendobj); 105268649Sdelphij ZCMD_COPY(zc_fromobj); 106268649Sdelphij ZCMD_COPY(zc_createtxg); 107268649Sdelphij ZCMD_COPY(zc_stat); 108268649Sdelphij#undef ZCMD_COPY 109268649Sdelphij 110268649Sdelphij break; 111268649Sdelphij 112248571Smm case ZFS_CMD_COMPAT_DEADMAN: 113248571Smm zcdm_c = (void *)addr; 114248571Smm /* zc */ 115248571Smm strlcpy(zc->zc_name, zcdm_c->zc_name, MAXPATHLEN); 116248571Smm strlcpy(zc->zc_value, zcdm_c->zc_value, MAXPATHLEN * 2); 117248571Smm strlcpy(zc->zc_string, zcdm_c->zc_string, MAXPATHLEN); 118248571Smm zc->zc_guid = zcdm_c->zc_guid; 119248571Smm zc->zc_nvlist_conf = zcdm_c->zc_nvlist_conf; 120248571Smm zc->zc_nvlist_conf_size = zcdm_c->zc_nvlist_conf_size; 121248571Smm zc->zc_nvlist_src = zcdm_c->zc_nvlist_src; 122248571Smm zc->zc_nvlist_src_size = zcdm_c->zc_nvlist_src_size; 123248571Smm zc->zc_nvlist_dst = zcdm_c->zc_nvlist_dst; 124248571Smm zc->zc_nvlist_dst_size = zcdm_c->zc_nvlist_dst_size; 125248571Smm zc->zc_cookie = zcdm_c->zc_cookie; 126248571Smm zc->zc_objset_type = zcdm_c->zc_objset_type; 127248571Smm zc->zc_perm_action = zcdm_c->zc_perm_action; 128248571Smm zc->zc_history = zcdm_c->zc_history; 129248571Smm zc->zc_history_len = zcdm_c->zc_history_len; 130248571Smm zc->zc_history_offset = zcdm_c->zc_history_offset; 131248571Smm zc->zc_obj = zcdm_c->zc_obj; 132248571Smm zc->zc_iflags = zcdm_c->zc_iflags; 133248571Smm zc->zc_share = zcdm_c->zc_share; 134248571Smm zc->zc_jailid = zcdm_c->zc_jailid; 135248571Smm zc->zc_objset_stats = zcdm_c->zc_objset_stats; 136248571Smm zc->zc_begin_record = zcdm_c->zc_begin_record; 137248571Smm zc->zc_defer_destroy = zcdm_c->zc_defer_destroy; 138268649Sdelphij (void)zcdm_c->zc_temphold; 139248571Smm zc->zc_action_handle = zcdm_c->zc_action_handle; 140248571Smm zc->zc_cleanup_fd = zcdm_c->zc_cleanup_fd; 141248571Smm zc->zc_simple = zcdm_c->zc_simple; 142248571Smm bcopy(zcdm_c->zc_pad, zc->zc_pad, sizeof(zc->zc_pad)); 143248571Smm zc->zc_sendobj = zcdm_c->zc_sendobj; 144248571Smm zc->zc_fromobj = zcdm_c->zc_fromobj; 145248571Smm zc->zc_createtxg = zcdm_c->zc_createtxg; 146248571Smm zc->zc_stat = zcdm_c->zc_stat; 147248571Smm 148248571Smm /* zc_inject_record doesn't change in libzfs_core */ 149248571Smm zcdm_c->zc_inject_record = zc->zc_inject_record; 150248571Smm 151248571Smm /* we always assume zc_nvlist_dst_filled is true */ 152248571Smm zc->zc_nvlist_dst_filled = B_TRUE; 153268649Sdelphij break; 154248571Smm 155247540Smm case ZFS_CMD_COMPAT_V28: 156247540Smm zc28_c = (void *)addr; 157247540Smm 158247540Smm /* zc */ 159247540Smm strlcpy(zc->zc_name, zc28_c->zc_name, MAXPATHLEN); 160247540Smm strlcpy(zc->zc_value, zc28_c->zc_value, MAXPATHLEN * 2); 161247540Smm strlcpy(zc->zc_string, zc28_c->zc_string, MAXPATHLEN); 162247540Smm zc->zc_guid = zc28_c->zc_guid; 163247540Smm zc->zc_nvlist_conf = zc28_c->zc_nvlist_conf; 164247540Smm zc->zc_nvlist_conf_size = zc28_c->zc_nvlist_conf_size; 165247540Smm zc->zc_nvlist_src = zc28_c->zc_nvlist_src; 166247540Smm zc->zc_nvlist_src_size = zc28_c->zc_nvlist_src_size; 167247540Smm zc->zc_nvlist_dst = zc28_c->zc_nvlist_dst; 168247540Smm zc->zc_nvlist_dst_size = zc28_c->zc_nvlist_dst_size; 169247540Smm zc->zc_cookie = zc28_c->zc_cookie; 170247540Smm zc->zc_objset_type = zc28_c->zc_objset_type; 171247540Smm zc->zc_perm_action = zc28_c->zc_perm_action; 172247540Smm zc->zc_history = zc28_c->zc_history; 173247540Smm zc->zc_history_len = zc28_c->zc_history_len; 174247540Smm zc->zc_history_offset = zc28_c->zc_history_offset; 175247540Smm zc->zc_obj = zc28_c->zc_obj; 176247540Smm zc->zc_iflags = zc28_c->zc_iflags; 177247540Smm zc->zc_share = zc28_c->zc_share; 178247540Smm zc->zc_jailid = zc28_c->zc_jailid; 179247540Smm zc->zc_objset_stats = zc28_c->zc_objset_stats; 180247540Smm zc->zc_begin_record = zc28_c->zc_begin_record; 181247540Smm zc->zc_defer_destroy = zc28_c->zc_defer_destroy; 182268649Sdelphij (void)zc28_c->zc_temphold; 183247540Smm zc->zc_action_handle = zc28_c->zc_action_handle; 184247540Smm zc->zc_cleanup_fd = zc28_c->zc_cleanup_fd; 185247540Smm zc->zc_simple = zc28_c->zc_simple; 186247540Smm bcopy(zc28_c->zc_pad, zc->zc_pad, sizeof(zc->zc_pad)); 187247540Smm zc->zc_sendobj = zc28_c->zc_sendobj; 188247540Smm zc->zc_fromobj = zc28_c->zc_fromobj; 189247540Smm zc->zc_createtxg = zc28_c->zc_createtxg; 190247540Smm zc->zc_stat = zc28_c->zc_stat; 191247540Smm 192247540Smm /* zc->zc_inject_record */ 193247540Smm zc->zc_inject_record.zi_objset = 194247540Smm zc28_c->zc_inject_record.zi_objset; 195247540Smm zc->zc_inject_record.zi_object = 196247540Smm zc28_c->zc_inject_record.zi_object; 197247540Smm zc->zc_inject_record.zi_start = 198247540Smm zc28_c->zc_inject_record.zi_start; 199247540Smm zc->zc_inject_record.zi_end = 200247540Smm zc28_c->zc_inject_record.zi_end; 201247540Smm zc->zc_inject_record.zi_guid = 202247540Smm zc28_c->zc_inject_record.zi_guid; 203247540Smm zc->zc_inject_record.zi_level = 204247540Smm zc28_c->zc_inject_record.zi_level; 205247540Smm zc->zc_inject_record.zi_error = 206247540Smm zc28_c->zc_inject_record.zi_error; 207247540Smm zc->zc_inject_record.zi_type = 208247540Smm zc28_c->zc_inject_record.zi_type; 209247540Smm zc->zc_inject_record.zi_freq = 210247540Smm zc28_c->zc_inject_record.zi_freq; 211247540Smm zc->zc_inject_record.zi_failfast = 212247540Smm zc28_c->zc_inject_record.zi_failfast; 213247540Smm strlcpy(zc->zc_inject_record.zi_func, 214247540Smm zc28_c->zc_inject_record.zi_func, MAXNAMELEN); 215247540Smm zc->zc_inject_record.zi_iotype = 216247540Smm zc28_c->zc_inject_record.zi_iotype; 217247540Smm zc->zc_inject_record.zi_duration = 218247540Smm zc28_c->zc_inject_record.zi_duration; 219247540Smm zc->zc_inject_record.zi_timer = 220247540Smm zc28_c->zc_inject_record.zi_timer; 221247540Smm zc->zc_inject_record.zi_cmd = ZINJECT_UNINITIALIZED; 222247540Smm zc->zc_inject_record.zi_pad = 0; 223247540Smm break; 224247540Smm 225247540Smm case ZFS_CMD_COMPAT_V15: 226219089Spjd zc_c = (void *)addr; 227219089Spjd 228219089Spjd /* zc */ 229247540Smm strlcpy(zc->zc_name, zc_c->zc_name, MAXPATHLEN); 230247540Smm strlcpy(zc->zc_value, zc_c->zc_value, MAXPATHLEN); 231247540Smm strlcpy(zc->zc_string, zc_c->zc_string, MAXPATHLEN); 232219089Spjd zc->zc_guid = zc_c->zc_guid; 233219089Spjd zc->zc_nvlist_conf = zc_c->zc_nvlist_conf; 234219089Spjd zc->zc_nvlist_conf_size = zc_c->zc_nvlist_conf_size; 235219089Spjd zc->zc_nvlist_src = zc_c->zc_nvlist_src; 236219089Spjd zc->zc_nvlist_src_size = zc_c->zc_nvlist_src_size; 237219089Spjd zc->zc_nvlist_dst = zc_c->zc_nvlist_dst; 238219089Spjd zc->zc_nvlist_dst_size = zc_c->zc_nvlist_dst_size; 239219089Spjd zc->zc_cookie = zc_c->zc_cookie; 240219089Spjd zc->zc_objset_type = zc_c->zc_objset_type; 241219089Spjd zc->zc_perm_action = zc_c->zc_perm_action; 242219089Spjd zc->zc_history = zc_c->zc_history; 243219089Spjd zc->zc_history_len = zc_c->zc_history_len; 244219089Spjd zc->zc_history_offset = zc_c->zc_history_offset; 245219089Spjd zc->zc_obj = zc_c->zc_obj; 246219089Spjd zc->zc_share = zc_c->zc_share; 247219089Spjd zc->zc_jailid = zc_c->zc_jailid; 248219089Spjd zc->zc_objset_stats = zc_c->zc_objset_stats; 249219089Spjd zc->zc_begin_record = zc_c->zc_begin_record; 250219089Spjd 251219089Spjd /* zc->zc_inject_record */ 252219089Spjd zc->zc_inject_record.zi_objset = 253219089Spjd zc_c->zc_inject_record.zi_objset; 254219089Spjd zc->zc_inject_record.zi_object = 255219089Spjd zc_c->zc_inject_record.zi_object; 256219089Spjd zc->zc_inject_record.zi_start = 257219089Spjd zc_c->zc_inject_record.zi_start; 258219089Spjd zc->zc_inject_record.zi_end = 259219089Spjd zc_c->zc_inject_record.zi_end; 260219089Spjd zc->zc_inject_record.zi_guid = 261219089Spjd zc_c->zc_inject_record.zi_guid; 262219089Spjd zc->zc_inject_record.zi_level = 263219089Spjd zc_c->zc_inject_record.zi_level; 264219089Spjd zc->zc_inject_record.zi_error = 265219089Spjd zc_c->zc_inject_record.zi_error; 266219089Spjd zc->zc_inject_record.zi_type = 267219089Spjd zc_c->zc_inject_record.zi_type; 268219089Spjd zc->zc_inject_record.zi_freq = 269219089Spjd zc_c->zc_inject_record.zi_freq; 270219089Spjd zc->zc_inject_record.zi_failfast = 271219089Spjd zc_c->zc_inject_record.zi_failfast; 272247540Smm break; 273219089Spjd } 274219089Spjd} 275219089Spjd 276219089Spjdvoid 277248571Smmzfs_cmd_compat_put(zfs_cmd_t *zc, caddr_t addr, const int request, 278248571Smm const int cflag) 279219089Spjd{ 280219089Spjd zfs_cmd_v15_t *zc_c; 281247540Smm zfs_cmd_v28_t *zc28_c; 282248571Smm zfs_cmd_deadman_t *zcdm_c; 283268649Sdelphij zfs_cmd_zcmd_t *zcmd_c; 284219089Spjd 285219089Spjd switch (cflag) { 286268649Sdelphij case ZFS_CMD_COMPAT_ZCMD: 287268649Sdelphij zcmd_c = (void *)addr; 288268649Sdelphij /* zc */ 289268649Sdelphij strlcpy(zcmd_c->zc_name, zc->zc_name, MAXPATHLEN); 290268649Sdelphij strlcpy(zcmd_c->zc_value, zc->zc_value, MAXPATHLEN * 2); 291268649Sdelphij strlcpy(zcmd_c->zc_string, zc->zc_string, MAXPATHLEN); 292268649Sdelphij 293268649Sdelphij#define ZCMD_COPY(field) zcmd_c->field = zc->field 294268649Sdelphij ZCMD_COPY(zc_nvlist_src); 295268649Sdelphij ZCMD_COPY(zc_nvlist_src_size); 296268649Sdelphij ZCMD_COPY(zc_nvlist_dst); 297268649Sdelphij ZCMD_COPY(zc_nvlist_dst_size); 298268649Sdelphij ZCMD_COPY(zc_nvlist_dst_filled); 299268649Sdelphij ZCMD_COPY(zc_pad2); 300268649Sdelphij ZCMD_COPY(zc_history); 301268649Sdelphij ZCMD_COPY(zc_guid); 302268649Sdelphij ZCMD_COPY(zc_nvlist_conf); 303268649Sdelphij ZCMD_COPY(zc_nvlist_conf_size); 304268649Sdelphij ZCMD_COPY(zc_cookie); 305268649Sdelphij ZCMD_COPY(zc_objset_type); 306268649Sdelphij ZCMD_COPY(zc_perm_action); 307268649Sdelphij ZCMD_COPY(zc_history_len); 308268649Sdelphij ZCMD_COPY(zc_history_offset); 309268649Sdelphij ZCMD_COPY(zc_obj); 310268649Sdelphij ZCMD_COPY(zc_iflags); 311268649Sdelphij ZCMD_COPY(zc_share); 312268649Sdelphij ZCMD_COPY(zc_jailid); 313268649Sdelphij ZCMD_COPY(zc_objset_stats); 314268649Sdelphij 315268649Sdelphij /* 316268649Sdelphij * zc_begin_record, zc_inject_record didn't change in embedeed-data 317268649Sdelphij * block pointers 318268649Sdelphij * 319268649Sdelphij * TODO: CTASSERT? 320268649Sdelphij */ 321268649Sdelphij ZCMD_COPY(zc_begin_record); 322268649Sdelphij ZCMD_COPY(zc_inject_record); 323268649Sdelphij 324268649Sdelphij /* boolean_t -> uint32_t */ 325268649Sdelphij zcmd_c->zc_defer_destroy = (uint32_t)(zc->zc_defer_destroy); 326268649Sdelphij zcmd_c->zc_temphold = 0; 327268649Sdelphij 328268649Sdelphij ZCMD_COPY(zc_action_handle); 329268649Sdelphij ZCMD_COPY(zc_cleanup_fd); 330268649Sdelphij ZCMD_COPY(zc_simple); 331268649Sdelphij bcopy(zc->zc_pad, zcmd_c->zc_pad, sizeof(zcmd_c->zc_pad)); 332268649Sdelphij ZCMD_COPY(zc_sendobj); 333268649Sdelphij ZCMD_COPY(zc_fromobj); 334268649Sdelphij ZCMD_COPY(zc_createtxg); 335268649Sdelphij ZCMD_COPY(zc_stat); 336268649Sdelphij#undef ZCMD_COPY 337268649Sdelphij 338268649Sdelphij break; 339268649Sdelphij 340248571Smm case ZFS_CMD_COMPAT_DEADMAN: 341248571Smm zcdm_c = (void *)addr; 342248571Smm 343248571Smm strlcpy(zcdm_c->zc_name, zc->zc_name, MAXPATHLEN); 344248571Smm strlcpy(zcdm_c->zc_value, zc->zc_value, MAXPATHLEN * 2); 345248571Smm strlcpy(zcdm_c->zc_string, zc->zc_string, MAXPATHLEN); 346248571Smm zcdm_c->zc_guid = zc->zc_guid; 347248571Smm zcdm_c->zc_nvlist_conf = zc->zc_nvlist_conf; 348248571Smm zcdm_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size; 349248571Smm zcdm_c->zc_nvlist_src = zc->zc_nvlist_src; 350248571Smm zcdm_c->zc_nvlist_src_size = zc->zc_nvlist_src_size; 351248571Smm zcdm_c->zc_nvlist_dst = zc->zc_nvlist_dst; 352248571Smm zcdm_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size; 353248571Smm zcdm_c->zc_cookie = zc->zc_cookie; 354248571Smm zcdm_c->zc_objset_type = zc->zc_objset_type; 355248571Smm zcdm_c->zc_perm_action = zc->zc_perm_action; 356248571Smm zcdm_c->zc_history = zc->zc_history; 357248571Smm zcdm_c->zc_history_len = zc->zc_history_len; 358248571Smm zcdm_c->zc_history_offset = zc->zc_history_offset; 359248571Smm zcdm_c->zc_obj = zc->zc_obj; 360248571Smm zcdm_c->zc_iflags = zc->zc_iflags; 361248571Smm zcdm_c->zc_share = zc->zc_share; 362248571Smm zcdm_c->zc_jailid = zc->zc_jailid; 363248571Smm zcdm_c->zc_objset_stats = zc->zc_objset_stats; 364248571Smm zcdm_c->zc_begin_record = zc->zc_begin_record; 365248571Smm zcdm_c->zc_defer_destroy = zc->zc_defer_destroy; 366268649Sdelphij zcdm_c->zc_temphold = 0; 367248571Smm zcdm_c->zc_action_handle = zc->zc_action_handle; 368248571Smm zcdm_c->zc_cleanup_fd = zc->zc_cleanup_fd; 369248571Smm zcdm_c->zc_simple = zc->zc_simple; 370248571Smm bcopy(zc->zc_pad, zcdm_c->zc_pad, sizeof(zcdm_c->zc_pad)); 371248571Smm zcdm_c->zc_sendobj = zc->zc_sendobj; 372248571Smm zcdm_c->zc_fromobj = zc->zc_fromobj; 373248571Smm zcdm_c->zc_createtxg = zc->zc_createtxg; 374248571Smm zcdm_c->zc_stat = zc->zc_stat; 375248571Smm 376248571Smm /* zc_inject_record doesn't change in libzfs_core */ 377248571Smm zc->zc_inject_record = zcdm_c->zc_inject_record; 378248571Smm#ifndef _KERNEL 379248571Smm if (request == ZFS_IOC_RECV) 380248571Smm strlcpy(zcdm_c->zc_top_ds, 381248571Smm zc->zc_value + strlen(zc->zc_value) + 1, 382248571Smm (MAXPATHLEN * 2) - strlen(zc->zc_value) - 1); 383248571Smm#endif 384268649Sdelphij break; 385248571Smm 386247540Smm case ZFS_CMD_COMPAT_V28: 387247540Smm zc28_c = (void *)addr; 388247540Smm 389247540Smm strlcpy(zc28_c->zc_name, zc->zc_name, MAXPATHLEN); 390247540Smm strlcpy(zc28_c->zc_value, zc->zc_value, MAXPATHLEN * 2); 391247540Smm strlcpy(zc28_c->zc_string, zc->zc_string, MAXPATHLEN); 392247540Smm zc28_c->zc_guid = zc->zc_guid; 393247540Smm zc28_c->zc_nvlist_conf = zc->zc_nvlist_conf; 394247540Smm zc28_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size; 395247540Smm zc28_c->zc_nvlist_src = zc->zc_nvlist_src; 396247540Smm zc28_c->zc_nvlist_src_size = zc->zc_nvlist_src_size; 397247540Smm zc28_c->zc_nvlist_dst = zc->zc_nvlist_dst; 398247540Smm zc28_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size; 399247540Smm zc28_c->zc_cookie = zc->zc_cookie; 400247540Smm zc28_c->zc_objset_type = zc->zc_objset_type; 401247540Smm zc28_c->zc_perm_action = zc->zc_perm_action; 402247540Smm zc28_c->zc_history = zc->zc_history; 403247540Smm zc28_c->zc_history_len = zc->zc_history_len; 404247540Smm zc28_c->zc_history_offset = zc->zc_history_offset; 405247540Smm zc28_c->zc_obj = zc->zc_obj; 406247540Smm zc28_c->zc_iflags = zc->zc_iflags; 407247540Smm zc28_c->zc_share = zc->zc_share; 408247540Smm zc28_c->zc_jailid = zc->zc_jailid; 409247540Smm zc28_c->zc_objset_stats = zc->zc_objset_stats; 410247540Smm zc28_c->zc_begin_record = zc->zc_begin_record; 411247540Smm zc28_c->zc_defer_destroy = zc->zc_defer_destroy; 412268649Sdelphij zc28_c->zc_temphold = 0; 413247540Smm zc28_c->zc_action_handle = zc->zc_action_handle; 414247540Smm zc28_c->zc_cleanup_fd = zc->zc_cleanup_fd; 415247540Smm zc28_c->zc_simple = zc->zc_simple; 416247540Smm bcopy(zc->zc_pad, zc28_c->zc_pad, sizeof(zc28_c->zc_pad)); 417247540Smm zc28_c->zc_sendobj = zc->zc_sendobj; 418247540Smm zc28_c->zc_fromobj = zc->zc_fromobj; 419247540Smm zc28_c->zc_createtxg = zc->zc_createtxg; 420247540Smm zc28_c->zc_stat = zc->zc_stat; 421248571Smm#ifndef _KERNEL 422248571Smm if (request == ZFS_IOC_RECV) 423248571Smm strlcpy(zc28_c->zc_top_ds, 424248571Smm zc->zc_value + strlen(zc->zc_value) + 1, 425248571Smm MAXPATHLEN * 2 - strlen(zc->zc_value) - 1); 426248571Smm#endif 427247540Smm /* zc_inject_record */ 428247540Smm zc28_c->zc_inject_record.zi_objset = 429247540Smm zc->zc_inject_record.zi_objset; 430247540Smm zc28_c->zc_inject_record.zi_object = 431247540Smm zc->zc_inject_record.zi_object; 432247540Smm zc28_c->zc_inject_record.zi_start = 433247540Smm zc->zc_inject_record.zi_start; 434247540Smm zc28_c->zc_inject_record.zi_end = 435247540Smm zc->zc_inject_record.zi_end; 436247540Smm zc28_c->zc_inject_record.zi_guid = 437247540Smm zc->zc_inject_record.zi_guid; 438247540Smm zc28_c->zc_inject_record.zi_level = 439247540Smm zc->zc_inject_record.zi_level; 440247540Smm zc28_c->zc_inject_record.zi_error = 441247540Smm zc->zc_inject_record.zi_error; 442247540Smm zc28_c->zc_inject_record.zi_type = 443247540Smm zc->zc_inject_record.zi_type; 444247540Smm zc28_c->zc_inject_record.zi_freq = 445247540Smm zc->zc_inject_record.zi_freq; 446247540Smm zc28_c->zc_inject_record.zi_failfast = 447247540Smm zc->zc_inject_record.zi_failfast; 448247540Smm strlcpy(zc28_c->zc_inject_record.zi_func, 449247540Smm zc->zc_inject_record.zi_func, MAXNAMELEN); 450247540Smm zc28_c->zc_inject_record.zi_iotype = 451247540Smm zc->zc_inject_record.zi_iotype; 452247540Smm zc28_c->zc_inject_record.zi_duration = 453247540Smm zc->zc_inject_record.zi_duration; 454247540Smm zc28_c->zc_inject_record.zi_timer = 455247540Smm zc->zc_inject_record.zi_timer; 456247540Smm break; 457247540Smm 458219089Spjd case ZFS_CMD_COMPAT_V15: 459219089Spjd zc_c = (void *)addr; 460219089Spjd 461219089Spjd /* zc */ 462247540Smm strlcpy(zc_c->zc_name, zc->zc_name, MAXPATHLEN); 463247540Smm strlcpy(zc_c->zc_value, zc->zc_value, MAXPATHLEN); 464247540Smm strlcpy(zc_c->zc_string, zc->zc_string, MAXPATHLEN); 465219089Spjd zc_c->zc_guid = zc->zc_guid; 466219089Spjd zc_c->zc_nvlist_conf = zc->zc_nvlist_conf; 467219089Spjd zc_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size; 468219089Spjd zc_c->zc_nvlist_src = zc->zc_nvlist_src; 469219089Spjd zc_c->zc_nvlist_src_size = zc->zc_nvlist_src_size; 470219089Spjd zc_c->zc_nvlist_dst = zc->zc_nvlist_dst; 471219089Spjd zc_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size; 472219089Spjd zc_c->zc_cookie = zc->zc_cookie; 473219089Spjd zc_c->zc_objset_type = zc->zc_objset_type; 474219089Spjd zc_c->zc_perm_action = zc->zc_perm_action; 475219089Spjd zc_c->zc_history = zc->zc_history; 476219089Spjd zc_c->zc_history_len = zc->zc_history_len; 477219089Spjd zc_c->zc_history_offset = zc->zc_history_offset; 478219089Spjd zc_c->zc_obj = zc->zc_obj; 479219089Spjd zc_c->zc_share = zc->zc_share; 480219089Spjd zc_c->zc_jailid = zc->zc_jailid; 481219089Spjd zc_c->zc_objset_stats = zc->zc_objset_stats; 482219089Spjd zc_c->zc_begin_record = zc->zc_begin_record; 483219089Spjd 484219089Spjd /* zc_inject_record */ 485219089Spjd zc_c->zc_inject_record.zi_objset = 486219089Spjd zc->zc_inject_record.zi_objset; 487219089Spjd zc_c->zc_inject_record.zi_object = 488219089Spjd zc->zc_inject_record.zi_object; 489219089Spjd zc_c->zc_inject_record.zi_start = 490219089Spjd zc->zc_inject_record.zi_start; 491219089Spjd zc_c->zc_inject_record.zi_end = 492219089Spjd zc->zc_inject_record.zi_end; 493219089Spjd zc_c->zc_inject_record.zi_guid = 494219089Spjd zc->zc_inject_record.zi_guid; 495219089Spjd zc_c->zc_inject_record.zi_level = 496219089Spjd zc->zc_inject_record.zi_level; 497219089Spjd zc_c->zc_inject_record.zi_error = 498219089Spjd zc->zc_inject_record.zi_error; 499219089Spjd zc_c->zc_inject_record.zi_type = 500219089Spjd zc->zc_inject_record.zi_type; 501219089Spjd zc_c->zc_inject_record.zi_freq = 502219089Spjd zc->zc_inject_record.zi_freq; 503219089Spjd zc_c->zc_inject_record.zi_failfast = 504219089Spjd zc->zc_inject_record.zi_failfast; 505219089Spjd 506219089Spjd break; 507219089Spjd } 508219089Spjd} 509219089Spjd 510219089Spjdstatic int 511220447Smmzfs_ioctl_compat_get_nvlist(uint64_t nvl, size_t size, int iflag, 512220447Smm nvlist_t **nvp) 513219089Spjd{ 514220447Smm char *packed; 515220447Smm int error; 516220447Smm nvlist_t *list = NULL; 517219089Spjd 518220447Smm /* 519220447Smm * Read in and unpack the user-supplied nvlist. 520220447Smm */ 521220447Smm if (size == 0) 522220447Smm return (EINVAL); 523219089Spjd 524220447Smm#ifdef _KERNEL 525220447Smm packed = kmem_alloc(size, KM_SLEEP); 526220447Smm if ((error = ddi_copyin((void *)(uintptr_t)nvl, packed, size, 527220447Smm iflag)) != 0) { 528220447Smm kmem_free(packed, size); 529220447Smm return (error); 530220447Smm } 531220447Smm#else 532220447Smm packed = (void *)(uintptr_t)nvl; 533220447Smm#endif 534220447Smm 535220447Smm error = nvlist_unpack(packed, size, &list, 0); 536220447Smm 537220447Smm#ifdef _KERNEL 538220447Smm kmem_free(packed, size); 539220447Smm#endif 540220447Smm 541220447Smm if (error != 0) 542220447Smm return (error); 543220447Smm 544220447Smm *nvp = list; 545220447Smm return (0); 546219089Spjd} 547219089Spjd 548220447Smmstatic int 549220447Smmzfs_ioctl_compat_put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) 550220447Smm{ 551220447Smm char *packed = NULL; 552220447Smm int error = 0; 553220447Smm size_t size; 554220447Smm 555220447Smm VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); 556220447Smm 557220447Smm#ifdef _KERNEL 558220447Smm packed = kmem_alloc(size, KM_SLEEP); 559220447Smm VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 560220447Smm KM_SLEEP) == 0); 561220447Smm 562220447Smm if (ddi_copyout(packed, 563220447Smm (void *)(uintptr_t)zc->zc_nvlist_dst, size, zc->zc_iflags) != 0) 564220447Smm error = EFAULT; 565220447Smm kmem_free(packed, size); 566220447Smm#else 567220447Smm packed = (void *)(uintptr_t)zc->zc_nvlist_dst; 568220447Smm VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, 569220447Smm 0) == 0); 570220447Smm#endif 571220447Smm 572220447Smm zc->zc_nvlist_dst_size = size; 573220447Smm return (error); 574220447Smm} 575220447Smm 576219089Spjdstatic void 577219089Spjdzfs_ioctl_compat_fix_stats_nvlist(nvlist_t *nvl) 578219089Spjd{ 579219089Spjd nvlist_t **child; 580219089Spjd nvlist_t *nvroot = NULL; 581219089Spjd vdev_stat_t *vs; 582219089Spjd uint_t c, children, nelem; 583219089Spjd 584219089Spjd if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_CHILDREN, 585219089Spjd &child, &children) == 0) { 586219089Spjd for (c = 0; c < children; c++) { 587219089Spjd zfs_ioctl_compat_fix_stats_nvlist(child[c]); 588219089Spjd } 589219089Spjd } 590219089Spjd 591219089Spjd if (nvlist_lookup_nvlist(nvl, ZPOOL_CONFIG_VDEV_TREE, 592219089Spjd &nvroot) == 0) 593219089Spjd zfs_ioctl_compat_fix_stats_nvlist(nvroot); 594219089Spjd#ifdef _KERNEL 595219089Spjd if ((nvlist_lookup_uint64_array(nvl, ZPOOL_CONFIG_VDEV_STATS, 596219089Spjd#else 597219089Spjd if ((nvlist_lookup_uint64_array(nvl, "stats", 598219089Spjd#endif 599219089Spjd 600219089Spjd (uint64_t **)&vs, &nelem) == 0)) { 601219089Spjd nvlist_add_uint64_array(nvl, 602219089Spjd#ifdef _KERNEL 603219089Spjd "stats", 604219089Spjd#else 605219089Spjd ZPOOL_CONFIG_VDEV_STATS, 606219089Spjd#endif 607219089Spjd (uint64_t *)vs, nelem); 608219089Spjd#ifdef _KERNEL 609219089Spjd nvlist_remove(nvl, ZPOOL_CONFIG_VDEV_STATS, 610219089Spjd#else 611219089Spjd nvlist_remove(nvl, "stats", 612219089Spjd#endif 613219089Spjd DATA_TYPE_UINT64_ARRAY); 614219089Spjd } 615219089Spjd} 616219089Spjd 617220447Smmstatic int 618247540Smmzfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int nc) 619219089Spjd{ 620219089Spjd nvlist_t *nv, *nvp = NULL; 621219089Spjd nvpair_t *elem; 622220447Smm int error; 623219089Spjd 624220447Smm if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst, 625220447Smm zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0) 626220447Smm return (error); 627219089Spjd 628247540Smm if (nc == 5) { /* ZFS_IOC_POOL_STATS */ 629219089Spjd elem = NULL; 630219089Spjd while ((elem = nvlist_next_nvpair(nv, elem)) != NULL) { 631219089Spjd if (nvpair_value_nvlist(elem, &nvp) == 0) 632219089Spjd zfs_ioctl_compat_fix_stats_nvlist(nvp); 633219089Spjd } 634219089Spjd elem = NULL; 635219089Spjd } else 636219089Spjd zfs_ioctl_compat_fix_stats_nvlist(nv); 637219089Spjd 638220447Smm error = zfs_ioctl_compat_put_nvlist(zc, nv); 639219089Spjd 640219089Spjd nvlist_free(nv); 641220447Smm 642220447Smm return (error); 643219089Spjd} 644219089Spjd 645220447Smmstatic int 646219089Spjdzfs_ioctl_compat_pool_get_props(zfs_cmd_t *zc) 647219089Spjd{ 648219089Spjd nvlist_t *nv, *nva = NULL; 649220447Smm int error; 650219089Spjd 651220447Smm if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst, 652220447Smm zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0) 653220447Smm return (error); 654219089Spjd 655219089Spjd#ifdef _KERNEL 656219089Spjd if (nvlist_lookup_nvlist(nv, "allocated", &nva) == 0) { 657219089Spjd nvlist_add_nvlist(nv, "used", nva); 658219089Spjd nvlist_remove(nv, "allocated", DATA_TYPE_NVLIST); 659219089Spjd } 660219089Spjd 661219089Spjd if (nvlist_lookup_nvlist(nv, "free", &nva) == 0) { 662219089Spjd nvlist_add_nvlist(nv, "available", nva); 663219089Spjd nvlist_remove(nv, "free", DATA_TYPE_NVLIST); 664219089Spjd } 665219089Spjd#else 666219089Spjd if (nvlist_lookup_nvlist(nv, "used", &nva) == 0) { 667219089Spjd nvlist_add_nvlist(nv, "allocated", nva); 668219089Spjd nvlist_remove(nv, "used", DATA_TYPE_NVLIST); 669219089Spjd } 670219089Spjd 671219089Spjd if (nvlist_lookup_nvlist(nv, "available", &nva) == 0) { 672219089Spjd nvlist_add_nvlist(nv, "free", nva); 673219089Spjd nvlist_remove(nv, "available", DATA_TYPE_NVLIST); 674219089Spjd } 675219089Spjd#endif 676219089Spjd 677220447Smm error = zfs_ioctl_compat_put_nvlist(zc, nv); 678219089Spjd 679219089Spjd nvlist_free(nv); 680220447Smm 681220447Smm return (error); 682219089Spjd} 683219089Spjd 684219089Spjd#ifndef _KERNEL 685219089Spjdint 686248571Smmzcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag) 687219089Spjd{ 688219089Spjd int nc, ret; 689219089Spjd void *zc_c; 690219089Spjd unsigned long ncmd; 691249319Smm zfs_iocparm_t zp; 692219089Spjd 693247540Smm switch (cflag) { 694247540Smm case ZFS_CMD_COMPAT_NONE: 695249319Smm ncmd = _IOWR('Z', request, struct zfs_iocparm); 696249319Smm zp.zfs_cmd = (uint64_t)zc; 697249319Smm zp.zfs_cmd_size = sizeof(zfs_cmd_t); 698249319Smm zp.zfs_ioctl_version = ZFS_IOCVER_CURRENT; 699249319Smm return (ioctl(fd, ncmd, &zp)); 700268786Sdelphij case ZFS_CMD_COMPAT_ZCMD: 701268786Sdelphij ncmd = _IOWR('Z', request, struct zfs_iocparm); 702268786Sdelphij zp.zfs_cmd = (uint64_t)zc; 703268786Sdelphij zp.zfs_cmd_size = sizeof(zfs_cmd_zcmd_t); 704268786Sdelphij zp.zfs_ioctl_version = ZFS_IOCVER_ZCMD; 705268786Sdelphij return (ioctl(fd, ncmd, &zp)); 706249319Smm case ZFS_CMD_COMPAT_LZC: 707248571Smm ncmd = _IOWR('Z', request, struct zfs_cmd); 708249319Smm return (ioctl(fd, ncmd, zc)); 709248571Smm case ZFS_CMD_COMPAT_DEADMAN: 710248571Smm zc_c = malloc(sizeof(zfs_cmd_deadman_t)); 711248571Smm ncmd = _IOWR('Z', request, struct zfs_cmd_deadman); 712248571Smm break; 713247540Smm case ZFS_CMD_COMPAT_V28: 714247540Smm zc_c = malloc(sizeof(zfs_cmd_v28_t)); 715248571Smm ncmd = _IOWR('Z', request, struct zfs_cmd_v28); 716247540Smm break; 717247540Smm case ZFS_CMD_COMPAT_V15: 718248571Smm nc = zfs_ioctl_v28_to_v15[request]; 719219089Spjd zc_c = malloc(sizeof(zfs_cmd_v15_t)); 720219089Spjd ncmd = _IOWR('Z', nc, struct zfs_cmd_v15); 721247540Smm break; 722247540Smm default: 723219089Spjd return (EINVAL); 724247540Smm } 725219089Spjd 726248571Smm if (ZFS_IOCREQ(ncmd) == ZFS_IOC_COMPAT_FAIL) 727219089Spjd return (ENOTSUP); 728219089Spjd 729248571Smm zfs_cmd_compat_put(zc, (caddr_t)zc_c, request, cflag); 730248571Smm 731219089Spjd ret = ioctl(fd, ncmd, zc_c); 732219089Spjd if (cflag == ZFS_CMD_COMPAT_V15 && 733248571Smm nc == ZFS_IOC_POOL_IMPORT) 734248571Smm ret = ioctl(fd, _IOWR('Z', ZFS_IOC_POOL_CONFIGS, 735219089Spjd struct zfs_cmd_v15), zc_c); 736219089Spjd zfs_cmd_compat_get(zc, (caddr_t)zc_c, cflag); 737219089Spjd free(zc_c); 738219089Spjd 739247540Smm if (cflag == ZFS_CMD_COMPAT_V15) { 740247540Smm switch (nc) { 741248571Smm case ZFS_IOC_POOL_IMPORT: 742248571Smm case ZFS_IOC_POOL_CONFIGS: 743248571Smm case ZFS_IOC_POOL_STATS: 744248571Smm case ZFS_IOC_POOL_TRYIMPORT: 745247540Smm zfs_ioctl_compat_fix_stats(zc, nc); 746247540Smm break; 747247540Smm case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */ 748247540Smm zfs_ioctl_compat_pool_get_props(zc); 749247540Smm break; 750247540Smm } 751219089Spjd } 752219089Spjd 753219089Spjd return (ret); 754219089Spjd} 755219089Spjd#else /* _KERNEL */ 756248571Smmint 757219089Spjdzfs_ioctl_compat_pre(zfs_cmd_t *zc, int *vec, const int cflag) 758219089Spjd{ 759248571Smm int error = 0; 760248571Smm 761248571Smm /* are we creating a clone? */ 762248571Smm if (*vec == ZFS_IOC_CREATE && zc->zc_value[0] != '\0') 763248571Smm *vec = ZFS_IOC_CLONE; 764248571Smm 765248571Smm if (cflag == ZFS_CMD_COMPAT_V15) { 766219089Spjd switch (*vec) { 767219089Spjd 768219089Spjd case 7: /* ZFS_IOC_POOL_SCRUB (v15) */ 769219089Spjd zc->zc_cookie = POOL_SCAN_SCRUB; 770219089Spjd break; 771219089Spjd } 772248571Smm } 773248571Smm 774248571Smm return (error); 775219089Spjd} 776219089Spjd 777219089Spjdvoid 778219089Spjdzfs_ioctl_compat_post(zfs_cmd_t *zc, int vec, const int cflag) 779219089Spjd{ 780219089Spjd if (cflag == ZFS_CMD_COMPAT_V15) { 781219089Spjd switch (vec) { 782248571Smm case ZFS_IOC_POOL_CONFIGS: 783248571Smm case ZFS_IOC_POOL_STATS: 784248571Smm case ZFS_IOC_POOL_TRYIMPORT: 785219089Spjd zfs_ioctl_compat_fix_stats(zc, vec); 786219089Spjd break; 787219089Spjd case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */ 788219089Spjd zfs_ioctl_compat_pool_get_props(zc); 789219089Spjd break; 790219089Spjd } 791219089Spjd } 792219089Spjd} 793248571Smm 794248571Smmnvlist_t * 795248571Smmzfs_ioctl_compat_innvl(zfs_cmd_t *zc, nvlist_t * innvl, const int vec, 796248571Smm const int cflag) 797248571Smm{ 798248571Smm nvlist_t *nvl, *tmpnvl, *hnvl; 799248571Smm nvpair_t *elem; 800248571Smm char *poolname, *snapname; 801248571Smm int err; 802248571Smm 803268786Sdelphij if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC || 804268786Sdelphij cflag == ZFS_CMD_COMPAT_ZCMD) 805248571Smm goto out; 806248571Smm 807248571Smm switch (vec) { 808248571Smm case ZFS_IOC_CREATE: 809248571Smm nvl = fnvlist_alloc(); 810248571Smm fnvlist_add_int32(nvl, "type", zc->zc_objset_type); 811248571Smm if (innvl != NULL) { 812248571Smm fnvlist_add_nvlist(nvl, "props", innvl); 813248571Smm nvlist_free(innvl); 814248571Smm } 815248571Smm return (nvl); 816248571Smm break; 817248571Smm case ZFS_IOC_CLONE: 818248571Smm nvl = fnvlist_alloc(); 819248571Smm fnvlist_add_string(nvl, "origin", zc->zc_value); 820248571Smm if (innvl != NULL) { 821248571Smm fnvlist_add_nvlist(nvl, "props", innvl); 822248571Smm nvlist_free(innvl); 823248571Smm } 824248571Smm return (nvl); 825248571Smm break; 826248571Smm case ZFS_IOC_SNAPSHOT: 827248571Smm if (innvl == NULL) 828248571Smm goto out; 829248571Smm nvl = fnvlist_alloc(); 830248571Smm fnvlist_add_nvlist(nvl, "props", innvl); 831248571Smm tmpnvl = fnvlist_alloc(); 832248571Smm snapname = kmem_asprintf("%s@%s", zc->zc_name, zc->zc_value); 833248571Smm fnvlist_add_boolean(tmpnvl, snapname); 834248571Smm kmem_free(snapname, strlen(snapname + 1)); 835248571Smm /* check if we are doing a recursive snapshot */ 836248571Smm if (zc->zc_cookie) 837248571Smm dmu_get_recursive_snaps_nvl(zc->zc_name, zc->zc_value, 838248571Smm tmpnvl); 839248571Smm fnvlist_add_nvlist(nvl, "snaps", tmpnvl); 840248571Smm fnvlist_free(tmpnvl); 841248571Smm nvlist_free(innvl); 842248571Smm /* strip dataset part from zc->zc_name */ 843248571Smm zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0'; 844248571Smm return (nvl); 845248571Smm break; 846248571Smm case ZFS_IOC_SPACE_SNAPS: 847248571Smm nvl = fnvlist_alloc(); 848248571Smm fnvlist_add_string(nvl, "firstsnap", zc->zc_value); 849248571Smm if (innvl != NULL) 850248571Smm nvlist_free(innvl); 851248571Smm return (nvl); 852248571Smm break; 853248571Smm case ZFS_IOC_DESTROY_SNAPS: 854248571Smm if (innvl == NULL && cflag == ZFS_CMD_COMPAT_DEADMAN) 855248571Smm goto out; 856248571Smm nvl = fnvlist_alloc(); 857248571Smm if (innvl != NULL) { 858248571Smm fnvlist_add_nvlist(nvl, "snaps", innvl); 859248571Smm } else { 860248571Smm /* 861248571Smm * We are probably called by even older binaries, 862248571Smm * allocate and populate nvlist with recursive 863248571Smm * snapshots 864248571Smm */ 865263407Sdelphij if (zfs_component_namecheck(zc->zc_value, NULL, 866248571Smm NULL) == 0) { 867248571Smm tmpnvl = fnvlist_alloc(); 868248571Smm if (dmu_get_recursive_snaps_nvl(zc->zc_name, 869248571Smm zc->zc_value, tmpnvl) == 0) 870248571Smm fnvlist_add_nvlist(nvl, "snaps", 871248571Smm tmpnvl); 872248571Smm nvlist_free(tmpnvl); 873248571Smm } 874248571Smm } 875248571Smm if (innvl != NULL) 876248571Smm nvlist_free(innvl); 877248571Smm /* strip dataset part from zc->zc_name */ 878248571Smm zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0'; 879248571Smm return (nvl); 880248571Smm break; 881248571Smm case ZFS_IOC_HOLD: 882248571Smm nvl = fnvlist_alloc(); 883248571Smm tmpnvl = fnvlist_alloc(); 884248571Smm if (zc->zc_cleanup_fd != -1) 885248571Smm fnvlist_add_int32(nvl, "cleanup_fd", 886248571Smm (int32_t)zc->zc_cleanup_fd); 887248571Smm if (zc->zc_cookie) { 888248571Smm hnvl = fnvlist_alloc(); 889248571Smm if (dmu_get_recursive_snaps_nvl(zc->zc_name, 890248571Smm zc->zc_value, hnvl) == 0) { 891248571Smm elem = NULL; 892248571Smm while ((elem = nvlist_next_nvpair(hnvl, 893248571Smm elem)) != NULL) { 894248571Smm nvlist_add_string(tmpnvl, 895248571Smm nvpair_name(elem), zc->zc_string); 896248571Smm } 897248571Smm } 898248571Smm nvlist_free(hnvl); 899248571Smm } else { 900248571Smm snapname = kmem_asprintf("%s@%s", zc->zc_name, 901248571Smm zc->zc_value); 902248571Smm nvlist_add_string(tmpnvl, snapname, zc->zc_string); 903248571Smm kmem_free(snapname, strlen(snapname + 1)); 904248571Smm } 905248571Smm fnvlist_add_nvlist(nvl, "holds", tmpnvl); 906248571Smm nvlist_free(tmpnvl); 907248571Smm if (innvl != NULL) 908248571Smm nvlist_free(innvl); 909248571Smm /* strip dataset part from zc->zc_name */ 910248571Smm zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0'; 911248571Smm return (nvl); 912248571Smm break; 913248571Smm case ZFS_IOC_RELEASE: 914248571Smm nvl = fnvlist_alloc(); 915248571Smm tmpnvl = fnvlist_alloc(); 916248571Smm if (zc->zc_cookie) { 917248571Smm hnvl = fnvlist_alloc(); 918248571Smm if (dmu_get_recursive_snaps_nvl(zc->zc_name, 919248571Smm zc->zc_value, hnvl) == 0) { 920248571Smm elem = NULL; 921248571Smm while ((elem = nvlist_next_nvpair(hnvl, 922248571Smm elem)) != NULL) { 923248571Smm fnvlist_add_boolean(tmpnvl, 924248571Smm zc->zc_string); 925248571Smm fnvlist_add_nvlist(nvl, 926248571Smm nvpair_name(elem), tmpnvl); 927248571Smm } 928248571Smm } 929248571Smm nvlist_free(hnvl); 930248571Smm } else { 931248571Smm snapname = kmem_asprintf("%s@%s", zc->zc_name, 932248571Smm zc->zc_value); 933248571Smm fnvlist_add_boolean(tmpnvl, zc->zc_string); 934248571Smm fnvlist_add_nvlist(nvl, snapname, tmpnvl); 935248571Smm kmem_free(snapname, strlen(snapname + 1)); 936248571Smm } 937248571Smm nvlist_free(tmpnvl); 938248571Smm if (innvl != NULL) 939248571Smm nvlist_free(innvl); 940248571Smm /* strip dataset part from zc->zc_name */ 941248571Smm zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0'; 942248571Smm return (nvl); 943248571Smm break; 944248571Smm } 945248571Smmout: 946248571Smm return (innvl); 947248571Smm} 948248571Smm 949248571Smmnvlist_t * 950248571Smmzfs_ioctl_compat_outnvl(zfs_cmd_t *zc, nvlist_t * outnvl, const int vec, 951248571Smm const int cflag) 952248571Smm{ 953248571Smm nvlist_t *tmpnvl; 954248571Smm 955268786Sdelphij if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC || 956268786Sdelphij cflag == ZFS_CMD_COMPAT_ZCMD) 957248571Smm return (outnvl); 958248571Smm 959248571Smm switch (vec) { 960248571Smm case ZFS_IOC_SPACE_SNAPS: 961248571Smm (void) nvlist_lookup_uint64(outnvl, "used", &zc->zc_cookie); 962248571Smm (void) nvlist_lookup_uint64(outnvl, "compressed", 963248571Smm &zc->zc_objset_type); 964248571Smm (void) nvlist_lookup_uint64(outnvl, "uncompressed", 965248571Smm &zc->zc_perm_action); 966248571Smm nvlist_free(outnvl); 967248571Smm /* return empty outnvl */ 968248571Smm tmpnvl = fnvlist_alloc(); 969248571Smm return (tmpnvl); 970248571Smm break; 971248571Smm case ZFS_IOC_CREATE: 972248571Smm case ZFS_IOC_CLONE: 973248571Smm case ZFS_IOC_HOLD: 974248571Smm case ZFS_IOC_RELEASE: 975248571Smm nvlist_free(outnvl); 976248571Smm /* return empty outnvl */ 977248571Smm tmpnvl = fnvlist_alloc(); 978248571Smm return (tmpnvl); 979248571Smm break; 980248571Smm } 981248571Smm 982248571Smm return (outnvl); 983248571Smm} 984219089Spjd#endif /* KERNEL */ 985