diff --git a/include/os/freebsd/zfs/sys/zfs_ioctl_compat.h b/include/os/freebsd/zfs/sys/zfs_ioctl_compat.h index 79b30b5088c4..34757a486028 100644 --- a/include/os/freebsd/zfs/sys/zfs_ioctl_compat.h +++ b/include/os/freebsd/zfs/sys/zfs_ioctl_compat.h @@ -1,159 +1,172 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2014 Xin Li . All rights reserved. * Copyright 2013 Martin Matuska . All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_ZFS_IOCTL_COMPAT_H #define _SYS_ZFS_IOCTL_COMPAT_H #include #include #include #include #include #ifdef _KERNEL #include #endif /* _KERNEL */ +/* + * Legacy ioctl support allows compatibility with pre-OpenZFS tools on + * FreeBSD. The need for it will eventually pass (perhaps after FreeBSD + * 12 is well out of support), at which point this code can be removed. + * For now, downstream consumers may choose to disable this code by + * removing the following define. + */ +#define ZFS_LEGACY_SUPPORT + #ifdef __cplusplus extern "C" { #endif /* * Backwards ioctl compatibility */ /* ioctl versions for vfs.zfs.version.ioctl */ #define ZFS_IOCVER_UNDEF -1 #define ZFS_IOCVER_NONE 0 #define ZFS_IOCVER_DEADMAN 1 #define ZFS_IOCVER_LZC 2 #define ZFS_IOCVER_ZCMD 3 #define ZFS_IOCVER_EDBP 4 #define ZFS_IOCVER_RESUME 5 #define ZFS_IOCVER_INLANES 6 #define ZFS_IOCVER_PAD 7 #define ZFS_IOCVER_LEGACY ZFS_IOCVER_PAD #define ZFS_IOCVER_OZFS 15 /* compatibility conversion flag */ #define ZFS_CMD_COMPAT_NONE 0 #define ZFS_CMD_COMPAT_V15 1 #define ZFS_CMD_COMPAT_V28 2 #define ZFS_CMD_COMPAT_DEADMAN 3 #define ZFS_CMD_COMPAT_LZC 4 #define ZFS_CMD_COMPAT_ZCMD 5 #define ZFS_CMD_COMPAT_EDBP 6 #define ZFS_CMD_COMPAT_RESUME 7 #define ZFS_CMD_COMPAT_INLANES 8 #define ZFS_CMD_COMPAT_LEGACY 9 #define ZFS_IOC_COMPAT_PASS 254 #define ZFS_IOC_COMPAT_FAIL 255 #define ZFS_IOCREQ(ioreq) ((ioreq) & 0xff) typedef struct zfs_iocparm { uint32_t zfs_ioctl_version; uint64_t zfs_cmd; uint64_t zfs_cmd_size; } zfs_iocparm_t; +#ifdef ZFS_LEGACY_SUPPORT #define LEGACY_MAXPATHLEN 1024 #define LEGACY_MAXNAMELEN 256 /* * Note: this struct must have the same layout in 32-bit and 64-bit, so * that 32-bit processes (like /sbin/zfs) can pass it to the 64-bit * kernel. Therefore, we add padding to it so that no "hidden" padding * is automatically added on 64-bit (but not on 32-bit). */ typedef struct zfs_cmd_legacy { char zc_name[LEGACY_MAXPATHLEN]; /* pool|dataset name */ uint64_t zc_nvlist_src; /* really (char *) */ uint64_t zc_nvlist_src_size; uint64_t zc_nvlist_dst; /* really (char *) */ uint64_t zc_nvlist_dst_size; boolean_t zc_nvlist_dst_filled; /* put an nvlist in dst? */ int zc_pad2; /* * The following members are for legacy ioctls which haven't been * converted to the new method. */ uint64_t zc_history; /* really (char *) */ char zc_value[LEGACY_MAXPATHLEN * 2]; char zc_string[LEGACY_MAXNAMELEN]; uint64_t zc_guid; uint64_t zc_nvlist_conf; /* really (char *) */ uint64_t zc_nvlist_conf_size; uint64_t zc_cookie; uint64_t zc_objset_type; uint64_t zc_perm_action; uint64_t zc_history_len; uint64_t zc_history_offset; uint64_t zc_obj; uint64_t zc_iflags; /* internal to zfs(7fs) */ zfs_share_t zc_share; uint64_t zc_jailid; dmu_objset_stats_t zc_objset_stats; dmu_replay_record_t zc_begin_record; zinject_record_t zc_inject_record; uint32_t zc_defer_destroy; uint32_t zc_flags; uint64_t zc_action_handle; int zc_cleanup_fd; uint8_t zc_simple; uint8_t zc_pad3[3]; boolean_t zc_resumable; uint32_t zc_pad4; uint64_t zc_sendobj; uint64_t zc_fromobj; uint64_t zc_createtxg; zfs_stat_t zc_stat; } zfs_cmd_legacy_t; +#endif #ifdef _KERNEL int zfs_ioctl_compat_pre(zfs_cmd_t *, int *, const int); void zfs_ioctl_compat_post(zfs_cmd_t *, const int, const int); nvlist_t *zfs_ioctl_compat_innvl(zfs_cmd_t *, nvlist_t *, const int, const int); nvlist_t *zfs_ioctl_compat_outnvl(zfs_cmd_t *, nvlist_t *, const int, const int); #endif /* _KERNEL */ +#ifdef ZFS_LEGACY_SUPPORT int zfs_ioctl_legacy_to_ozfs(int request); int zfs_ioctl_ozfs_to_legacy(int request); void zfs_cmd_legacy_to_ozfs(zfs_cmd_legacy_t *src, zfs_cmd_t *dst); void zfs_cmd_ozfs_to_legacy(zfs_cmd_t *src, zfs_cmd_legacy_t *dst); +#endif void zfs_cmd_compat_put(zfs_cmd_t *, caddr_t, const int, const int); #ifdef __cplusplus } #endif #endif /* _SYS_ZFS_IOCTL_COMPAT_H */ diff --git a/lib/libzfs_core/os/freebsd/libzfs_core_ioctl.c b/lib/libzfs_core/os/freebsd/libzfs_core_ioctl.c index 36fbbd88c2ac..72f8f393039a 100644 --- a/lib/libzfs_core/os/freebsd/libzfs_core_ioctl.c +++ b/lib/libzfs_core/os/freebsd/libzfs_core_ioctl.c @@ -1,123 +1,134 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ #include #include #include #include #include #include #include int zfs_ioctl_version = ZFS_IOCVER_UNDEF; /* * Get zfs_ioctl_version */ static int get_zfs_ioctl_version(void) { size_t ver_size; int ver = ZFS_IOCVER_NONE; ver_size = sizeof (ver); sysctlbyname("vfs.zfs.version.ioctl", &ver, &ver_size, NULL, 0); return (ver); } static int zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag) { - int newrequest, ret; + int ret; +#ifdef ZFS_LEGACY_SUPPORT + int newrequest; void *zc_c = NULL; +#endif unsigned long ncmd; zfs_iocparm_t zp; switch (cflag) { case ZFS_CMD_COMPAT_NONE: ncmd = _IOWR('Z', request, zfs_iocparm_t); zp.zfs_cmd = (uint64_t)(uintptr_t)zc; zp.zfs_cmd_size = sizeof (zfs_cmd_t); zp.zfs_ioctl_version = ZFS_IOCVER_OZFS; break; +#ifdef ZFS_LEGACY_SUPPORT case ZFS_CMD_COMPAT_LEGACY: newrequest = zfs_ioctl_ozfs_to_legacy(request); ncmd = _IOWR('Z', newrequest, zfs_iocparm_t); zc_c = malloc(sizeof (zfs_cmd_legacy_t)); zfs_cmd_ozfs_to_legacy(zc, zc_c); zp.zfs_cmd = (uint64_t)(uintptr_t)zc_c; zp.zfs_cmd_size = sizeof (zfs_cmd_legacy_t); zp.zfs_ioctl_version = ZFS_IOCVER_LEGACY; break; +#endif default: abort(); return (EINVAL); } ret = ioctl(fd, ncmd, &zp); if (ret) { +#ifdef ZFS_LEGACY_SUPPORT if (zc_c) free(zc_c); +#endif return (ret); } +#ifdef ZFS_LEGACY_SUPPORT if (zc_c) { zfs_cmd_legacy_to_ozfs(zc_c, zc); free(zc_c); } +#endif return (ret); } /* * This is FreeBSD version of ioctl, because Solaris' ioctl() updates * zc_nvlist_dst_size even if an error is returned, on FreeBSD if an * error is returned zc_nvlist_dst_size won't be updated. */ int lzc_ioctl_fd(int fd, unsigned long request, zfs_cmd_t *zc) { size_t oldsize; int ret, cflag = ZFS_CMD_COMPAT_NONE; if (zfs_ioctl_version == ZFS_IOCVER_UNDEF) zfs_ioctl_version = get_zfs_ioctl_version(); switch (zfs_ioctl_version) { +#ifdef ZFS_LEGACY_SUPPORT case ZFS_IOCVER_LEGACY: cflag = ZFS_CMD_COMPAT_LEGACY; break; +#endif case ZFS_IOCVER_OZFS: cflag = ZFS_CMD_COMPAT_NONE; break; default: errx(1, "unrecognized zfs ioctl version %d", zfs_ioctl_version); } oldsize = zc->zc_nvlist_dst_size; ret = zcmd_ioctl_compat(fd, request, zc, cflag); if (ret == 0 && oldsize < zc->zc_nvlist_dst_size) { ret = -1; errno = ENOMEM; } return (ret); } diff --git a/lib/libzpool/util.c b/lib/libzpool/util.c index a310255d7a7d..551f1294d31f 100644 --- a/lib/libzpool/util.c +++ b/lib/libzpool/util.c @@ -1,357 +1,361 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 by Delphix. All rights reserved. * Copyright 2017 Jason King * Copyright (c) 2017, Intel Corporation. */ #include #include #include #include #include #include #include #include #include #include #include #include /* * Routines needed by more than one client of libzpool. */ static void show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent) { vdev_stat_t *vs; vdev_stat_t *v0 = { 0 }; uint64_t sec; uint64_t is_log = 0; nvlist_t **child; uint_t c, children; char used[6], avail[6]; char rops[6], wops[6], rbytes[6], wbytes[6], rerr[6], werr[6], cerr[6]; v0 = umem_zalloc(sizeof (*v0), UMEM_NOFAIL); if (indent == 0 && desc != NULL) { (void) printf(" " " capacity operations bandwidth ---- errors ----\n"); (void) printf("description " "used avail read write read write read write cksum\n"); } if (desc != NULL) { const char *suffix = ""; char *bias = NULL; char bias_suffix[32]; (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, &is_log); (void) nvlist_lookup_string(nv, ZPOOL_CONFIG_ALLOCATION_BIAS, &bias); if (nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &c) != 0) vs = v0; if (bias != NULL) { (void) snprintf(bias_suffix, sizeof (bias_suffix), " (%s)", bias); suffix = bias_suffix; } else if (is_log) { suffix = " (log)"; } sec = MAX(1, vs->vs_timestamp / NANOSEC); nicenum(vs->vs_alloc, used, sizeof (used)); nicenum(vs->vs_space - vs->vs_alloc, avail, sizeof (avail)); nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops, sizeof (rops)); nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops, sizeof (wops)); nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes, sizeof (rbytes)); nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes, sizeof (wbytes)); nicenum(vs->vs_read_errors, rerr, sizeof (rerr)); nicenum(vs->vs_write_errors, werr, sizeof (werr)); nicenum(vs->vs_checksum_errors, cerr, sizeof (cerr)); (void) printf("%*s%s%*s%*s%*s %5s %5s %5s %5s %5s %5s %5s\n", indent, "", desc, (int)(indent+strlen(desc)-25-(vs->vs_space ? 0 : 12)), suffix, vs->vs_space ? 6 : 0, vs->vs_space ? used : "", vs->vs_space ? 6 : 0, vs->vs_space ? avail : "", rops, wops, rbytes, wbytes, rerr, werr, cerr); } umem_free(v0, sizeof (*v0)); if (nvlist_lookup_nvlist_array(nv, ctype, &child, &children) != 0) return; for (c = 0; c < children; c++) { nvlist_t *cnv = child[c]; char *cname = NULL, *tname; uint64_t np; int len; if (nvlist_lookup_string(cnv, ZPOOL_CONFIG_PATH, &cname) && nvlist_lookup_string(cnv, ZPOOL_CONFIG_TYPE, &cname)) cname = (char *)""; len = strlen(cname) + 2; tname = umem_zalloc(len, UMEM_NOFAIL); (void) strlcpy(tname, cname, len); if (nvlist_lookup_uint64(cnv, ZPOOL_CONFIG_NPARITY, &np) == 0) tname[strlen(tname)] = '0' + np; show_vdev_stats(tname, ctype, cnv, indent + 2); umem_free(tname, len); } } void show_pool_stats(spa_t *spa) { nvlist_t *config, *nvroot; char *name; VERIFY(spa_get_stats(spa_name(spa), &config, NULL, 0) == 0); VERIFY(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); VERIFY(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, &name) == 0); show_vdev_stats(name, ZPOOL_CONFIG_CHILDREN, nvroot, 0); show_vdev_stats(NULL, ZPOOL_CONFIG_L2CACHE, nvroot, 0); show_vdev_stats(NULL, ZPOOL_CONFIG_SPARES, nvroot, 0); nvlist_free(config); } /* *k_out must be freed by the caller */ static int set_global_var_parse_kv(const char *arg, char **k_out, u_longlong_t *v_out) { int err; VERIFY(arg); char *d = strdup(arg); char *save = NULL; char *k = strtok_r(d, "=", &save); char *v_str = strtok_r(NULL, "=", &save); char *follow = strtok_r(NULL, "=", &save); if (k == NULL || v_str == NULL || follow != NULL) { err = EINVAL; goto err_free; } u_longlong_t val = strtoull(v_str, NULL, 0); if (val > UINT32_MAX) { fprintf(stderr, "Value for global variable '%s' must " "be a 32-bit unsigned integer, got '%s'\n", k, v_str); err = EOVERFLOW; goto err_free; } *k_out = strdup(k); *v_out = val; free(d); return (0); err_free: free(d); return (err); } /* * Sets given global variable in libzpool to given unsigned 32-bit value. * arg: "=" */ int set_global_var(char const *arg) { void *zpoolhdl; char *varname; u_longlong_t val; int ret; #ifndef _ZFS_LITTLE_ENDIAN /* * On big endian systems changing a 64-bit variable would set the high * 32 bits instead of the low 32 bits, which could cause unexpected * results. */ fprintf(stderr, "Setting global variables is only supported on " "little-endian systems\n"); ret = ENOTSUP; goto out_ret; #endif if ((ret = set_global_var_parse_kv(arg, &varname, &val)) != 0) { goto out_ret; } zpoolhdl = dlopen("libzpool.so", RTLD_LAZY); if (zpoolhdl != NULL) { uint32_t *var; var = dlsym(zpoolhdl, varname); if (var == NULL) { fprintf(stderr, "Global variable '%s' does not exist " "in libzpool.so\n", varname); ret = EINVAL; goto out_dlclose; } *var = (uint32_t)val; } else { fprintf(stderr, "Failed to open libzpool.so to set global " "variable\n"); ret = EIO; goto out_free; } ret = 0; out_dlclose: dlclose(zpoolhdl); out_free: free(varname); out_ret: return (ret); } static nvlist_t * refresh_config(void *unused, nvlist_t *tryconfig) { (void) unused; return (spa_tryimport(tryconfig)); } #if defined(__FreeBSD__) #include #include #include static int pool_active(void *unused, const char *name, uint64_t guid, boolean_t *isactive) { (void) unused, (void) guid; zfs_iocparm_t zp; zfs_cmd_t *zc = NULL; +#ifdef ZFS_LEGACY_SUPPORT zfs_cmd_legacy_t *zcl = NULL; +#endif unsigned long request; int ret; int fd = open(ZFS_DEV, O_RDWR | O_CLOEXEC); if (fd < 0) return (-1); /* * Use ZFS_IOC_POOL_STATS to check if the pool is active. We want to * avoid adding a dependency on libzfs_core solely for this ioctl(), * therefore we manually craft the stats command. Note that the command * ID is identical between the openzfs and legacy ioctl() formats. */ int ver = ZFS_IOCVER_NONE; size_t ver_size = sizeof (ver); sysctlbyname("vfs.zfs.version.ioctl", &ver, &ver_size, NULL, 0); switch (ver) { case ZFS_IOCVER_OZFS: zc = umem_zalloc(sizeof (zfs_cmd_t), UMEM_NOFAIL); (void) strlcpy(zc->zc_name, name, sizeof (zc->zc_name)); zp.zfs_cmd = (uint64_t)(uintptr_t)zc; zp.zfs_cmd_size = sizeof (zfs_cmd_t); zp.zfs_ioctl_version = ZFS_IOCVER_OZFS; request = _IOWR('Z', ZFS_IOC_POOL_STATS, zfs_iocparm_t); ret = ioctl(fd, request, &zp); free((void *)(uintptr_t)zc->zc_nvlist_dst); umem_free(zc, sizeof (zfs_cmd_t)); break; +#ifdef ZFS_LEGACY_SUPPORT case ZFS_IOCVER_LEGACY: zcl = umem_zalloc(sizeof (zfs_cmd_legacy_t), UMEM_NOFAIL); (void) strlcpy(zcl->zc_name, name, sizeof (zcl->zc_name)); zp.zfs_cmd = (uint64_t)(uintptr_t)zcl; zp.zfs_cmd_size = sizeof (zfs_cmd_legacy_t); zp.zfs_ioctl_version = ZFS_IOCVER_LEGACY; request = _IOWR('Z', ZFS_IOC_POOL_STATS, zfs_iocparm_t); ret = ioctl(fd, request, &zp); free((void *)(uintptr_t)zcl->zc_nvlist_dst); umem_free(zcl, sizeof (zfs_cmd_legacy_t)); break; +#endif default: fprintf(stderr, "unrecognized zfs ioctl version %d", ver); exit(1); } (void) close(fd); *isactive = (ret == 0); return (0); } #else static int pool_active(void *unused, const char *name, uint64_t guid, boolean_t *isactive) { (void) unused, (void) guid; int fd = open(ZFS_DEV, O_RDWR | O_CLOEXEC); if (fd < 0) return (-1); /* * Use ZFS_IOC_POOL_STATS to check if a pool is active. */ zfs_cmd_t *zcp = umem_zalloc(sizeof (zfs_cmd_t), UMEM_NOFAIL); (void) strlcpy(zcp->zc_name, name, sizeof (zcp->zc_name)); int ret = ioctl(fd, ZFS_IOC_POOL_STATS, zcp); free((void *)(uintptr_t)zcp->zc_nvlist_dst); umem_free(zcp, sizeof (zfs_cmd_t)); (void) close(fd); *isactive = (ret == 0); return (0); } #endif pool_config_ops_t libzpool_config_ops = { .pco_refresh_config = refresh_config, .pco_pool_active = pool_active, }; diff --git a/module/os/freebsd/zfs/kmod_core.c b/module/os/freebsd/zfs/kmod_core.c index 020ef6a39b5e..6885d565e26c 100644 --- a/module/os/freebsd/zfs/kmod_core.c +++ b/module/os/freebsd/zfs/kmod_core.c @@ -1,339 +1,351 @@ /* * Copyright (c) 2020 iXsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "zfs_comutil.h" #include "zfs_deleg.h" #include "zfs_namecheck.h" #include "zfs_prop.h" SYSCTL_DECL(_vfs_zfs); SYSCTL_DECL(_vfs_zfs_vdev); extern uint_t rrw_tsd_key; static int zfs_version_ioctl = ZFS_IOCVER_OZFS; SYSCTL_DECL(_vfs_zfs_version); SYSCTL_INT(_vfs_zfs_version, OID_AUTO, ioctl, CTLFLAG_RD, &zfs_version_ioctl, 0, "ZFS_IOCTL_VERSION"); static struct cdev *zfsdev; static struct root_hold_token *zfs_root_token; extern uint_t rrw_tsd_key; extern uint_t zfs_allow_log_key; extern uint_t zfs_geom_probe_vdev_key; static int zfs__init(void); static int zfs__fini(void); static void zfs_shutdown(void *, int); static eventhandler_tag zfs_shutdown_event_tag; #define ZFS_MIN_KSTACK_PAGES 4 static int zfsdev_ioctl(struct cdev *dev, ulong_t zcmd, caddr_t arg, int flag, struct thread *td) { uint_t len; int vecnum; zfs_iocparm_t *zp; zfs_cmd_t *zc; +#ifdef ZFS_LEGACY_SUPPORT zfs_cmd_legacy_t *zcl; +#endif int rc, error; void *uaddr; len = IOCPARM_LEN(zcmd); vecnum = zcmd & 0xff; zp = (void *)arg; uaddr = (void *)zp->zfs_cmd; error = 0; +#ifdef ZFS_LEGACY_SUPPORT zcl = NULL; +#endif if (len != sizeof (zfs_iocparm_t)) { printf("len %d vecnum: %d sizeof (zfs_cmd_t) %ju\n", len, vecnum, (uintmax_t)sizeof (zfs_cmd_t)); return (EINVAL); } zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); +#ifdef ZFS_LEGACY_SUPPORT /* * Remap ioctl code for legacy user binaries */ if (zp->zfs_ioctl_version == ZFS_IOCVER_LEGACY) { vecnum = zfs_ioctl_legacy_to_ozfs(vecnum); if (vecnum < 0) { kmem_free(zc, sizeof (zfs_cmd_t)); return (ENOTSUP); } zcl = kmem_zalloc(sizeof (zfs_cmd_legacy_t), KM_SLEEP); if (copyin(uaddr, zcl, sizeof (zfs_cmd_legacy_t))) { error = SET_ERROR(EFAULT); goto out; } zfs_cmd_legacy_to_ozfs(zcl, zc); - } else if (copyin(uaddr, zc, sizeof (zfs_cmd_t))) { + } else +#endif + if (copyin(uaddr, zc, sizeof (zfs_cmd_t))) { error = SET_ERROR(EFAULT); goto out; } error = zfsdev_ioctl_common(vecnum, zc, 0); +#ifdef ZFS_LEGACY_SUPPORT if (zcl) { zfs_cmd_ozfs_to_legacy(zc, zcl); rc = copyout(zcl, uaddr, sizeof (*zcl)); - } else { + } else +#endif + { rc = copyout(zc, uaddr, sizeof (*zc)); } if (error == 0 && rc != 0) error = SET_ERROR(EFAULT); out: +#ifdef ZFS_LEGACY_SUPPORT if (zcl) kmem_free(zcl, sizeof (zfs_cmd_legacy_t)); +#endif kmem_free(zc, sizeof (zfs_cmd_t)); MPASS(tsd_get(rrw_tsd_key) == NULL); return (error); } static void zfsdev_close(void *data) { zfsdev_state_destroy(data); } void zfsdev_private_set_state(void *priv __unused, zfsdev_state_t *zs) { devfs_set_cdevpriv(zs, zfsdev_close); } zfsdev_state_t * zfsdev_private_get_state(void *priv) { return (priv); } static int zfsdev_open(struct cdev *devp __unused, int flag __unused, int mode __unused, struct thread *td __unused) { int error; mutex_enter(&zfsdev_state_lock); error = zfsdev_state_init(NULL); mutex_exit(&zfsdev_state_lock); return (error); } static struct cdevsw zfs_cdevsw = { .d_version = D_VERSION, .d_open = zfsdev_open, .d_ioctl = zfsdev_ioctl, .d_name = ZFS_DRIVER }; int zfsdev_attach(void) { struct make_dev_args args; make_dev_args_init(&args); args.mda_flags = MAKEDEV_CHECKNAME | MAKEDEV_WAITOK; args.mda_devsw = &zfs_cdevsw; args.mda_cr = NULL; args.mda_uid = UID_ROOT; args.mda_gid = GID_OPERATOR; args.mda_mode = 0666; return (make_dev_s(&args, &zfsdev, ZFS_DRIVER)); } void zfsdev_detach(void) { if (zfsdev != NULL) destroy_dev(zfsdev); } int zfs__init(void) { int error; #if KSTACK_PAGES < ZFS_MIN_KSTACK_PAGES printf("ZFS NOTICE: KSTACK_PAGES is %d which could result in stack " "overflow panic!\nPlease consider adding " "'options KSTACK_PAGES=%d' to your kernel config\n", KSTACK_PAGES, ZFS_MIN_KSTACK_PAGES); #endif zfs_root_token = root_mount_hold("ZFS"); if ((error = zfs_kmod_init()) != 0) { printf("ZFS: Failed to Load ZFS Filesystem" ", rc = %d\n", error); root_mount_rel(zfs_root_token); return (error); } tsd_create(&zfs_geom_probe_vdev_key, NULL); printf("ZFS storage pool version: features support (" SPA_VERSION_STRING ")\n"); root_mount_rel(zfs_root_token); ddi_sysevent_init(); return (0); } int zfs__fini(void) { if (zfs_busy() || zvol_busy() || zio_injection_enabled) { return (EBUSY); } zfs_kmod_fini(); tsd_destroy(&zfs_geom_probe_vdev_key); return (0); } static void zfs_shutdown(void *arg __unused, int howto __unused) { /* * ZFS fini routines can not properly work in a panic-ed system. */ if (panicstr == NULL) zfs__fini(); } static int zfs_modevent(module_t mod, int type, void *unused __unused) { int err; switch (type) { case MOD_LOAD: err = zfs__init(); if (err == 0) zfs_shutdown_event_tag = EVENTHANDLER_REGISTER( shutdown_post_sync, zfs_shutdown, NULL, SHUTDOWN_PRI_FIRST); return (err); case MOD_UNLOAD: err = zfs__fini(); if (err == 0 && zfs_shutdown_event_tag != NULL) EVENTHANDLER_DEREGISTER(shutdown_post_sync, zfs_shutdown_event_tag); return (err); case MOD_SHUTDOWN: return (0); default: break; } return (EOPNOTSUPP); } static moduledata_t zfs_mod = { "zfsctrl", zfs_modevent, 0 }; #ifdef _KERNEL EVENTHANDLER_DEFINE(mountroot, spa_boot_init, NULL, 0); #endif DECLARE_MODULE(zfsctrl, zfs_mod, SI_SUB_CLOCKS, SI_ORDER_ANY); MODULE_VERSION(zfsctrl, 1); #if __FreeBSD_version > 1300092 MODULE_DEPEND(zfsctrl, xdr, 1, 1, 1); #else MODULE_DEPEND(zfsctrl, krpc, 1, 1, 1); #endif MODULE_DEPEND(zfsctrl, acl_nfs4, 1, 1, 1); MODULE_DEPEND(zfsctrl, crypto, 1, 1, 1); MODULE_DEPEND(zfsctrl, zlib, 1, 1, 1); diff --git a/module/os/freebsd/zfs/zfs_ioctl_compat.c b/module/os/freebsd/zfs/zfs_ioctl_compat.c index 08913ab05ddc..3ddffec91e83 100644 --- a/module/os/freebsd/zfs/zfs_ioctl_compat.c +++ b/module/os/freebsd/zfs/zfs_ioctl_compat.c @@ -1,363 +1,365 @@ /* * Copyright (c) 2020 iXsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include +#ifdef ZFS_LEGACY_SUPPORT enum zfs_ioc_legacy { ZFS_IOC_LEGACY_NONE = -1, ZFS_IOC_LEGACY_FIRST = 0, ZFS_LEGACY_IOC = ZFS_IOC_LEGACY_FIRST, ZFS_IOC_LEGACY_POOL_CREATE = ZFS_IOC_LEGACY_FIRST, ZFS_IOC_LEGACY_POOL_DESTROY, ZFS_IOC_LEGACY_POOL_IMPORT, ZFS_IOC_LEGACY_POOL_EXPORT, ZFS_IOC_LEGACY_POOL_CONFIGS, ZFS_IOC_LEGACY_POOL_STATS, ZFS_IOC_LEGACY_POOL_TRYIMPORT, ZFS_IOC_LEGACY_POOL_SCAN, ZFS_IOC_LEGACY_POOL_FREEZE, ZFS_IOC_LEGACY_POOL_UPGRADE, ZFS_IOC_LEGACY_POOL_GET_HISTORY, ZFS_IOC_LEGACY_VDEV_ADD, ZFS_IOC_LEGACY_VDEV_REMOVE, ZFS_IOC_LEGACY_VDEV_SET_STATE, ZFS_IOC_LEGACY_VDEV_ATTACH, ZFS_IOC_LEGACY_VDEV_DETACH, ZFS_IOC_LEGACY_VDEV_SETPATH, ZFS_IOC_LEGACY_VDEV_SETFRU, ZFS_IOC_LEGACY_OBJSET_STATS, ZFS_IOC_LEGACY_OBJSET_ZPLPROPS, ZFS_IOC_LEGACY_DATASET_LIST_NEXT, ZFS_IOC_LEGACY_SNAPSHOT_LIST_NEXT, ZFS_IOC_LEGACY_SET_PROP, ZFS_IOC_LEGACY_CREATE, ZFS_IOC_LEGACY_DESTROY, ZFS_IOC_LEGACY_ROLLBACK, ZFS_IOC_LEGACY_RENAME, ZFS_IOC_LEGACY_RECV, ZFS_IOC_LEGACY_SEND, ZFS_IOC_LEGACY_INJECT_FAULT, ZFS_IOC_LEGACY_CLEAR_FAULT, ZFS_IOC_LEGACY_INJECT_LIST_NEXT, ZFS_IOC_LEGACY_ERROR_LOG, ZFS_IOC_LEGACY_CLEAR, ZFS_IOC_LEGACY_PROMOTE, ZFS_IOC_LEGACY_DESTROY_SNAPS, ZFS_IOC_LEGACY_SNAPSHOT, ZFS_IOC_LEGACY_DSOBJ_TO_DSNAME, ZFS_IOC_LEGACY_OBJ_TO_PATH, ZFS_IOC_LEGACY_POOL_SET_PROPS, ZFS_IOC_LEGACY_POOL_GET_PROPS, ZFS_IOC_LEGACY_SET_FSACL, ZFS_IOC_LEGACY_GET_FSACL, ZFS_IOC_LEGACY_SHARE, ZFS_IOC_LEGACY_INHERIT_PROP, ZFS_IOC_LEGACY_SMB_ACL, ZFS_IOC_LEGACY_USERSPACE_ONE, ZFS_IOC_LEGACY_USERSPACE_MANY, ZFS_IOC_LEGACY_USERSPACE_UPGRADE, ZFS_IOC_LEGACY_HOLD, ZFS_IOC_LEGACY_RELEASE, ZFS_IOC_LEGACY_GET_HOLDS, ZFS_IOC_LEGACY_OBJSET_RECVD_PROPS, ZFS_IOC_LEGACY_VDEV_SPLIT, ZFS_IOC_LEGACY_NEXT_OBJ, ZFS_IOC_LEGACY_DIFF, ZFS_IOC_LEGACY_TMP_SNAPSHOT, ZFS_IOC_LEGACY_OBJ_TO_STATS, ZFS_IOC_LEGACY_JAIL, ZFS_IOC_LEGACY_UNJAIL, ZFS_IOC_LEGACY_POOL_REGUID, ZFS_IOC_LEGACY_SPACE_WRITTEN, ZFS_IOC_LEGACY_SPACE_SNAPS, ZFS_IOC_LEGACY_SEND_PROGRESS, ZFS_IOC_LEGACY_POOL_REOPEN, ZFS_IOC_LEGACY_LOG_HISTORY, ZFS_IOC_LEGACY_SEND_NEW, ZFS_IOC_LEGACY_SEND_SPACE, ZFS_IOC_LEGACY_CLONE, ZFS_IOC_LEGACY_BOOKMARK, ZFS_IOC_LEGACY_GET_BOOKMARKS, ZFS_IOC_LEGACY_DESTROY_BOOKMARKS, ZFS_IOC_LEGACY_NEXTBOOT, ZFS_IOC_LEGACY_CHANNEL_PROGRAM, ZFS_IOC_LEGACY_REMAP, ZFS_IOC_LEGACY_POOL_CHECKPOINT, ZFS_IOC_LEGACY_POOL_DISCARD_CHECKPOINT, ZFS_IOC_LEGACY_POOL_INITIALIZE, ZFS_IOC_LEGACY_POOL_SYNC, ZFS_IOC_LEGACY_LAST }; static unsigned long zfs_ioctl_legacy_to_ozfs_[] = { ZFS_IOC_POOL_CREATE, /* 0x00 */ ZFS_IOC_POOL_DESTROY, /* 0x01 */ ZFS_IOC_POOL_IMPORT, /* 0x02 */ ZFS_IOC_POOL_EXPORT, /* 0x03 */ ZFS_IOC_POOL_CONFIGS, /* 0x04 */ ZFS_IOC_POOL_STATS, /* 0x05 */ ZFS_IOC_POOL_TRYIMPORT, /* 0x06 */ ZFS_IOC_POOL_SCAN, /* 0x07 */ ZFS_IOC_POOL_FREEZE, /* 0x08 */ ZFS_IOC_POOL_UPGRADE, /* 0x09 */ ZFS_IOC_POOL_GET_HISTORY, /* 0x0a */ ZFS_IOC_VDEV_ADD, /* 0x0b */ ZFS_IOC_VDEV_REMOVE, /* 0x0c */ ZFS_IOC_VDEV_SET_STATE, /* 0x0d */ ZFS_IOC_VDEV_ATTACH, /* 0x0e */ ZFS_IOC_VDEV_DETACH, /* 0x0f */ ZFS_IOC_VDEV_SETPATH, /* 0x10 */ ZFS_IOC_VDEV_SETFRU, /* 0x11 */ ZFS_IOC_OBJSET_STATS, /* 0x12 */ ZFS_IOC_OBJSET_ZPLPROPS, /* 0x13 */ ZFS_IOC_DATASET_LIST_NEXT, /* 0x14 */ ZFS_IOC_SNAPSHOT_LIST_NEXT, /* 0x15 */ ZFS_IOC_SET_PROP, /* 0x16 */ ZFS_IOC_CREATE, /* 0x17 */ ZFS_IOC_DESTROY, /* 0x18 */ ZFS_IOC_ROLLBACK, /* 0x19 */ ZFS_IOC_RENAME, /* 0x1a */ ZFS_IOC_RECV, /* 0x1b */ ZFS_IOC_SEND, /* 0x1c */ ZFS_IOC_INJECT_FAULT, /* 0x1d */ ZFS_IOC_CLEAR_FAULT, /* 0x1e */ ZFS_IOC_INJECT_LIST_NEXT, /* 0x1f */ ZFS_IOC_ERROR_LOG, /* 0x20 */ ZFS_IOC_CLEAR, /* 0x21 */ ZFS_IOC_PROMOTE, /* 0x22 */ /* start of mismatch */ ZFS_IOC_DESTROY_SNAPS, /* 0x23:0x3b */ ZFS_IOC_SNAPSHOT, /* 0x24:0x23 */ ZFS_IOC_DSOBJ_TO_DSNAME, /* 0x25:0x24 */ ZFS_IOC_OBJ_TO_PATH, /* 0x26:0x25 */ ZFS_IOC_POOL_SET_PROPS, /* 0x27:0x26 */ ZFS_IOC_POOL_GET_PROPS, /* 0x28:0x27 */ ZFS_IOC_SET_FSACL, /* 0x29:0x28 */ ZFS_IOC_GET_FSACL, /* 0x30:0x29 */ ZFS_IOC_SHARE, /* 0x2b:0x2a */ ZFS_IOC_INHERIT_PROP, /* 0x2c:0x2b */ ZFS_IOC_SMB_ACL, /* 0x2d:0x2c */ ZFS_IOC_USERSPACE_ONE, /* 0x2e:0x2d */ ZFS_IOC_USERSPACE_MANY, /* 0x2f:0x2e */ ZFS_IOC_USERSPACE_UPGRADE, /* 0x30:0x2f */ ZFS_IOC_HOLD, /* 0x31:0x30 */ ZFS_IOC_RELEASE, /* 0x32:0x31 */ ZFS_IOC_GET_HOLDS, /* 0x33:0x32 */ ZFS_IOC_OBJSET_RECVD_PROPS, /* 0x34:0x33 */ ZFS_IOC_VDEV_SPLIT, /* 0x35:0x34 */ ZFS_IOC_NEXT_OBJ, /* 0x36:0x35 */ ZFS_IOC_DIFF, /* 0x37:0x36 */ ZFS_IOC_TMP_SNAPSHOT, /* 0x38:0x37 */ ZFS_IOC_OBJ_TO_STATS, /* 0x39:0x38 */ ZFS_IOC_JAIL, /* 0x3a:0xc2 */ ZFS_IOC_UNJAIL, /* 0x3b:0xc3 */ ZFS_IOC_POOL_REGUID, /* 0x3c:0x3c */ ZFS_IOC_SPACE_WRITTEN, /* 0x3d:0x39 */ ZFS_IOC_SPACE_SNAPS, /* 0x3e:0x3a */ ZFS_IOC_SEND_PROGRESS, /* 0x3f:0x3e */ ZFS_IOC_POOL_REOPEN, /* 0x40:0x3d */ ZFS_IOC_LOG_HISTORY, /* 0x41:0x3f */ ZFS_IOC_SEND_NEW, /* 0x42:0x40 */ ZFS_IOC_SEND_SPACE, /* 0x43:0x41 */ ZFS_IOC_CLONE, /* 0x44:0x42 */ ZFS_IOC_BOOKMARK, /* 0x45:0x43 */ ZFS_IOC_GET_BOOKMARKS, /* 0x46:0x44 */ ZFS_IOC_DESTROY_BOOKMARKS, /* 0x47:0x45 */ ZFS_IOC_NEXTBOOT, /* 0x48:0xc1 */ ZFS_IOC_CHANNEL_PROGRAM, /* 0x49:0x48 */ ZFS_IOC_REMAP, /* 0x4a:0x4c */ ZFS_IOC_POOL_CHECKPOINT, /* 0x4b:0x4d */ ZFS_IOC_POOL_DISCARD_CHECKPOINT, /* 0x4c:0x4e */ ZFS_IOC_POOL_INITIALIZE, /* 0x4d:0x4f */ }; static unsigned long zfs_ioctl_ozfs_to_legacy_common_[] = { ZFS_IOC_POOL_CREATE, /* 0x00 */ ZFS_IOC_POOL_DESTROY, /* 0x01 */ ZFS_IOC_POOL_IMPORT, /* 0x02 */ ZFS_IOC_POOL_EXPORT, /* 0x03 */ ZFS_IOC_POOL_CONFIGS, /* 0x04 */ ZFS_IOC_POOL_STATS, /* 0x05 */ ZFS_IOC_POOL_TRYIMPORT, /* 0x06 */ ZFS_IOC_POOL_SCAN, /* 0x07 */ ZFS_IOC_POOL_FREEZE, /* 0x08 */ ZFS_IOC_POOL_UPGRADE, /* 0x09 */ ZFS_IOC_POOL_GET_HISTORY, /* 0x0a */ ZFS_IOC_VDEV_ADD, /* 0x0b */ ZFS_IOC_VDEV_REMOVE, /* 0x0c */ ZFS_IOC_VDEV_SET_STATE, /* 0x0d */ ZFS_IOC_VDEV_ATTACH, /* 0x0e */ ZFS_IOC_VDEV_DETACH, /* 0x0f */ ZFS_IOC_VDEV_SETPATH, /* 0x10 */ ZFS_IOC_VDEV_SETFRU, /* 0x11 */ ZFS_IOC_OBJSET_STATS, /* 0x12 */ ZFS_IOC_OBJSET_ZPLPROPS, /* 0x13 */ ZFS_IOC_DATASET_LIST_NEXT, /* 0x14 */ ZFS_IOC_SNAPSHOT_LIST_NEXT, /* 0x15 */ ZFS_IOC_SET_PROP, /* 0x16 */ ZFS_IOC_CREATE, /* 0x17 */ ZFS_IOC_DESTROY, /* 0x18 */ ZFS_IOC_ROLLBACK, /* 0x19 */ ZFS_IOC_RENAME, /* 0x1a */ ZFS_IOC_RECV, /* 0x1b */ ZFS_IOC_SEND, /* 0x1c */ ZFS_IOC_INJECT_FAULT, /* 0x1d */ ZFS_IOC_CLEAR_FAULT, /* 0x1e */ ZFS_IOC_INJECT_LIST_NEXT, /* 0x1f */ ZFS_IOC_ERROR_LOG, /* 0x20 */ ZFS_IOC_CLEAR, /* 0x21 */ ZFS_IOC_PROMOTE, /* 0x22 */ /* start of mismatch */ ZFS_IOC_LEGACY_SNAPSHOT, /* 0x23 */ ZFS_IOC_LEGACY_DSOBJ_TO_DSNAME, /* 0x24 */ ZFS_IOC_LEGACY_OBJ_TO_PATH, /* 0x25 */ ZFS_IOC_LEGACY_POOL_SET_PROPS, /* 0x26 */ ZFS_IOC_LEGACY_POOL_GET_PROPS, /* 0x27 */ ZFS_IOC_LEGACY_SET_FSACL, /* 0x28 */ ZFS_IOC_LEGACY_GET_FSACL, /* 0x29 */ ZFS_IOC_LEGACY_SHARE, /* 0x2a */ ZFS_IOC_LEGACY_INHERIT_PROP, /* 0x2b */ ZFS_IOC_LEGACY_SMB_ACL, /* 0x2c */ ZFS_IOC_LEGACY_USERSPACE_ONE, /* 0x2d */ ZFS_IOC_LEGACY_USERSPACE_MANY, /* 0x2e */ ZFS_IOC_LEGACY_USERSPACE_UPGRADE, /* 0x2f */ ZFS_IOC_LEGACY_HOLD, /* 0x30 */ ZFS_IOC_LEGACY_RELEASE, /* 0x31 */ ZFS_IOC_LEGACY_GET_HOLDS, /* 0x32 */ ZFS_IOC_LEGACY_OBJSET_RECVD_PROPS, /* 0x33 */ ZFS_IOC_LEGACY_VDEV_SPLIT, /* 0x34 */ ZFS_IOC_LEGACY_NEXT_OBJ, /* 0x35 */ ZFS_IOC_LEGACY_DIFF, /* 0x36 */ ZFS_IOC_LEGACY_TMP_SNAPSHOT, /* 0x37 */ ZFS_IOC_LEGACY_OBJ_TO_STATS, /* 0x38 */ ZFS_IOC_LEGACY_SPACE_WRITTEN, /* 0x39 */ ZFS_IOC_LEGACY_SPACE_SNAPS, /* 0x3a */ ZFS_IOC_LEGACY_DESTROY_SNAPS, /* 0x3b */ ZFS_IOC_LEGACY_POOL_REGUID, /* 0x3c */ ZFS_IOC_LEGACY_POOL_REOPEN, /* 0x3d */ ZFS_IOC_LEGACY_SEND_PROGRESS, /* 0x3e */ ZFS_IOC_LEGACY_LOG_HISTORY, /* 0x3f */ ZFS_IOC_LEGACY_SEND_NEW, /* 0x40 */ ZFS_IOC_LEGACY_SEND_SPACE, /* 0x41 */ ZFS_IOC_LEGACY_CLONE, /* 0x42 */ ZFS_IOC_LEGACY_BOOKMARK, /* 0x43 */ ZFS_IOC_LEGACY_GET_BOOKMARKS, /* 0x44 */ ZFS_IOC_LEGACY_DESTROY_BOOKMARKS, /* 0x45 */ ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_RECV_NEW */ ZFS_IOC_LEGACY_POOL_SYNC, /* 0x47 */ ZFS_IOC_LEGACY_CHANNEL_PROGRAM, /* 0x48 */ ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_LOAD_KEY */ ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_UNLOAD_KEY */ ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_CHANGE_KEY */ ZFS_IOC_LEGACY_REMAP, /* 0x4c */ ZFS_IOC_LEGACY_POOL_CHECKPOINT, /* 0x4d */ ZFS_IOC_LEGACY_POOL_DISCARD_CHECKPOINT, /* 0x4e */ ZFS_IOC_LEGACY_POOL_INITIALIZE, /* 0x4f */ ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_POOL_TRIM */ ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_REDACT */ ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_GET_BOOKMARK_PROPS */ ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_WAIT */ ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_WAIT_FS */ }; static unsigned long zfs_ioctl_ozfs_to_legacy_platform_[] = { ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_EVENTS_NEXT */ ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_EVENTS_CLEAR */ ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_EVENTS_SEEK */ ZFS_IOC_LEGACY_NEXTBOOT, ZFS_IOC_LEGACY_JAIL, ZFS_IOC_LEGACY_UNJAIL, ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_SET_BOOTENV */ ZFS_IOC_LEGACY_NONE, /* ZFS_IOC_GET_BOOTENV */ }; int zfs_ioctl_legacy_to_ozfs(int request) { if (request >= sizeof (zfs_ioctl_legacy_to_ozfs_)/sizeof (long)) return (-1); return (zfs_ioctl_legacy_to_ozfs_[request]); } int zfs_ioctl_ozfs_to_legacy(int request) { if (request >= ZFS_IOC_LAST) return (-1); if (request > ZFS_IOC_PLATFORM) { request -= ZFS_IOC_PLATFORM + 1; return (zfs_ioctl_ozfs_to_legacy_platform_[request]); } if (request >= sizeof (zfs_ioctl_ozfs_to_legacy_common_)/sizeof (long)) return (-1); return (zfs_ioctl_ozfs_to_legacy_common_[request]); } void zfs_cmd_legacy_to_ozfs(zfs_cmd_legacy_t *src, zfs_cmd_t *dst) { memcpy(dst, src, offsetof(zfs_cmd_t, zc_objset_stats)); *&dst->zc_objset_stats = *&src->zc_objset_stats; memcpy(&dst->zc_begin_record, &src->zc_begin_record, offsetof(zfs_cmd_t, zc_sendobj) - offsetof(zfs_cmd_t, zc_begin_record)); memcpy(&dst->zc_sendobj, &src->zc_sendobj, sizeof (zfs_cmd_t) - 8 - offsetof(zfs_cmd_t, zc_sendobj)); dst->zc_zoneid = src->zc_jailid; } void zfs_cmd_ozfs_to_legacy(zfs_cmd_t *src, zfs_cmd_legacy_t *dst) { memcpy(dst, src, offsetof(zfs_cmd_t, zc_objset_stats)); *&dst->zc_objset_stats = *&src->zc_objset_stats; *&dst->zc_begin_record.drr_u.drr_begin = *&src->zc_begin_record; dst->zc_begin_record.drr_payloadlen = 0; dst->zc_begin_record.drr_type = 0; memcpy(&dst->zc_inject_record, &src->zc_inject_record, offsetof(zfs_cmd_t, zc_sendobj) - offsetof(zfs_cmd_t, zc_inject_record)); dst->zc_resumable = B_FALSE; memcpy(&dst->zc_sendobj, &src->zc_sendobj, sizeof (zfs_cmd_t) - 8 - offsetof(zfs_cmd_t, zc_sendobj)); dst->zc_jailid = src->zc_zoneid; } +#endif /* ZFS_LEGACY_SUPPORT */