From ac66f4a90bc292312cfe14b014e649292b6bbf85 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Tue, 5 Mar 2013 22:51:11 +0000 Subject: [PATCH 01/17] libzfs_core depends on libnvpair, explicitly say this in Makefile.inc1. This fixes build with make -j. --- Makefile.inc1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.inc1 b/Makefile.inc1 index 6114bb729230..20b3bd39a60b 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -1420,6 +1420,7 @@ _cddl_lib_libumem= cddl/lib/libumem _cddl_lib_libnvpair= cddl/lib/libnvpair _cddl_lib_libzfs_core= cddl/lib/libzfs_core _cddl_lib= cddl/lib +cddl/lib/libzfs_core__L: cddl/lib/libnvpair__L .endif .if ${MK_CRYPT} != "no" From 227d24fc596b9d658fafa7f5125a63611d67ae31 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Tue, 5 Mar 2013 22:58:53 +0000 Subject: [PATCH 02/17] Use adx2 instead of adx in the second vsprintf, this fixes a panic. --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c index 6ac8a933cc91..15d3050c6362 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c @@ -450,7 +450,7 @@ log_internal(nvlist_t *nvl, const char *operation, spa_t *spa, va_copy(adx2, adx); msg = kmem_alloc(vsnprintf(NULL, 0, fmt, adx) + 1, KM_SLEEP); - (void) vsprintf(msg, fmt, adx); + (void) vsprintf(msg, fmt, adx2); fnvlist_add_string(nvl, ZPOOL_HIST_INT_STR, msg); strfree(msg); From 2f79ac7f21545d993cde29ab9a38c4aaae470034 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Wed, 6 Mar 2013 01:21:56 +0000 Subject: [PATCH 03/17] Diff reduction with Illumos --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index d2833c2f187b..12c907b9771a 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -5801,11 +5801,11 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t addr, int flag, { zfs_cmd_t *zc; uint_t vecnum; -#ifdef illumos int error, rc, len; +#ifdef illumos minor_t minor = getminor(dev); #else - int cflag, cmd, error, rc, len; + int cflag, cmd; cred_t *cr = td->td_ucred; #endif const zfs_ioc_vec_t *vec; @@ -5989,7 +5989,7 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t addr, int flag, zfs_cmd_compat_put(zc, addr, cflag); } - kmem_free(zc, sizeof(zfs_cmd_t)); + kmem_free(zc, sizeof (zfs_cmd_t)); return (error); } From db49d41d8ac7121b181555f8b485f5696d7a86a5 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Wed, 6 Mar 2013 10:40:50 +0000 Subject: [PATCH 04/17] Move libzfs compat functions to libzfs_compat.h This header is used by both libzfs_core and libzfs libraries --- .../lib/libzfs/common/libzfs_compat.h | 94 +++++++++++++++++++ .../lib/libzfs/common/libzfs_impl.h | 60 +----------- .../lib/libzfs_core/common/libzfs_core.c | 2 +- .../lib/libzfs_core/common/libzfs_core.h | 1 + 4 files changed, 97 insertions(+), 60 deletions(-) create mode 100644 cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h new file mode 100644 index 000000000000..b6654b456c3a --- /dev/null +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h @@ -0,0 +1,94 @@ +/* + * CDDL HEADER SART + * + * 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 http://www.opensolaris.org/os/licensing. + * 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) 2013 Martin Matuska . All rights reserved. + */ + +#ifndef _LIBZFS_COMPAT_H +#define _LIBZFS_COMPAT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static int zfs_kernel_version = 0; +static int zfs_ioctl_version = 0; + +/* + * 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. + */ +static __inline int +zcmd_ioctl(int fd, int request, zfs_cmd_t *zc) +{ + unsigned long cmd; + size_t oldsize, zfs_kernel_version_size, zfs_ioctl_version_size; + int version, ret, cflag = ZFS_CMD_COMPAT_NONE; + + cmd = _IOWR('Z', request, struct zfs_cmd); + + zfs_ioctl_version_size = sizeof(zfs_ioctl_version); + if (zfs_ioctl_version == 0) { + sysctlbyname("vfs.zfs.version.ioctl", &zfs_ioctl_version, + &zfs_ioctl_version_size, NULL, 0); + } + + /* + * If vfs.zfs.version.ioctl is not defined, assume we have v28 + * compatible binaries and use vfs.zfs.version.spa to test for v15 + */ + if (zfs_ioctl_version < ZFS_IOCVER_DEADMAN) { + cflag = ZFS_CMD_COMPAT_V28; + zfs_kernel_version_size = sizeof(zfs_kernel_version); + + if (zfs_kernel_version == 0) { + sysctlbyname("vfs.zfs.version.spa", + &zfs_kernel_version, + &zfs_kernel_version_size, NULL, 0); + } + + if (zfs_kernel_version == SPA_VERSION_15 || + zfs_kernel_version == SPA_VERSION_14 || + zfs_kernel_version == SPA_VERSION_13) + cflag = ZFS_CMD_COMPAT_V15; + } + + oldsize = zc->zc_nvlist_dst_size; + ret = zcmd_ioctl_compat(fd, cmd, zc, cflag); + + if (ret == 0 && oldsize < zc->zc_nvlist_dst_size) { + ret = -1; + errno = ENOMEM; + } + + return (ret); +} +#define ioctl(fd, cmd, zc) zcmd_ioctl((fd), (cmd), (zc)) + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBZFS_COMPAT_H */ diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h index d55e942856d4..11a57a98ae60 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h @@ -40,8 +40,7 @@ #include #include #include - -#include "zfs_ioctl_compat.h" +#include #ifdef __cplusplus extern "C" { @@ -215,63 +214,6 @@ extern int zfs_unshare_proto(zfs_handle_t *, extern void libzfs_fru_clear(libzfs_handle_t *, boolean_t); -#ifndef sun -static int zfs_kernel_version = 0; -static int zfs_ioctl_version = 0; - -/* - * 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. - */ -static __inline int -zcmd_ioctl(int fd, int request, zfs_cmd_t *zc) -{ - unsigned long cmd; - size_t oldsize, zfs_kernel_version_size, zfs_ioctl_version_size; - int version, ret, cflag = ZFS_CMD_COMPAT_NONE; - - cmd = _IOWR('Z', request, struct zfs_cmd); - - zfs_ioctl_version_size = sizeof(zfs_ioctl_version); - if (zfs_ioctl_version == 0) { - sysctlbyname("vfs.zfs.version.ioctl", &zfs_ioctl_version, - &zfs_ioctl_version_size, NULL, 0); - } - - /* - * If vfs.zfs.version.ioctl is not defined, assume we have v28 - * compatible binaries and use vfs.zfs.version.spa to test for v15 - */ - if (zfs_ioctl_version < ZFS_IOCVER_DEADMAN) { - cflag = ZFS_CMD_COMPAT_V28; - zfs_kernel_version_size = sizeof(zfs_kernel_version); - - if (zfs_kernel_version == 0) { - sysctlbyname("vfs.zfs.version.spa", - &zfs_kernel_version, - &zfs_kernel_version_size, NULL, 0); - } - - if (zfs_kernel_version == SPA_VERSION_15 || - zfs_kernel_version == SPA_VERSION_14 || - zfs_kernel_version == SPA_VERSION_13) - cflag = ZFS_CMD_COMPAT_V15; - } - - oldsize = zc->zc_nvlist_dst_size; - ret = zcmd_ioctl_compat(fd, cmd, zc, cflag); - - if (ret == 0 && oldsize < zc->zc_nvlist_dst_size) { - ret = -1; - errno = ENOMEM; - } - - return (ret); -} -#define ioctl(fd, cmd, zc) zcmd_ioctl((fd), (cmd), (zc)) -#endif /* !sun */ - #ifdef __cplusplus } #endif diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c index 364d92ad4726..b6c28bee01ab 100644 --- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c @@ -84,7 +84,7 @@ #include #include #include -#include +#include static int g_fd; static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER; diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h index 9edc884a14d1..c8bfbefbdaf5 100644 --- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2013 by Martin Matuska . All rights reserved. */ #ifndef _LIBZFS_CORE_H From b3b6851c78010d0fd7377af67c72352da9522c80 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Wed, 6 Mar 2013 11:33:25 +0000 Subject: [PATCH 05/17] Add missing init functions Reduce diff to illumos --- .../opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index 12c907b9771a..6ba9192d4a92 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -5796,7 +5796,7 @@ zfsdev_close(void *data) } static int -zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t addr, int flag, +zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag, struct thread *td) { zfs_cmd_t *zc; @@ -5856,18 +5856,14 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t addr, int flag, zc = kmem_zalloc(sizeof(zfs_cmd_t), KM_SLEEP); bzero(zc, sizeof(zfs_cmd_t)); -#ifdef illumos error = ddi_copyin((void *)arg, zc, sizeof (zfs_cmd_t), flag); -#else - error = ddi_copyin((void *)addr, zc, sizeof (zfs_cmd_t), flag); -#endif if (error != 0) { error = EFAULT; goto out; } if (cflag != ZFS_CMD_COMPAT_NONE) { - zfs_cmd_compat_get(zc, addr, cflag); + zfs_cmd_compat_get(zc, arg, cflag); zfs_ioctl_compat_pre(zc, &vecnum, cflag); } @@ -5986,7 +5982,7 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t addr, int flag, if (cflag != ZFS_CMD_COMPAT_NONE) { zfs_ioctl_compat_post(zc, cmd, cflag); - zfs_cmd_compat_put(zc, addr, cflag); + zfs_cmd_compat_put(zc, arg, cflag); } kmem_free(zc, sizeof (zfs_cmd_t)); @@ -6216,9 +6212,11 @@ zfs_modevent(module_t mod, int type, void *unused __unused) spa_init(FREAD | FWRITE); zfs_init(); zvol_init(); + zfs_ioctl_init(); tsd_create(&zfs_fsyncer_key, NULL); - tsd_create(&rrw_tsd_key, NULL); + tsd_create(&rrw_tsd_key, rrw_tsd_destroy); + tsd_create(&zfs_allow_log_key, zfs_allow_log_destroy); printf("ZFS storage pool version: features support (" SPA_VERSION_STRING ")\n"); root_mount_rel(zfs_root_token); @@ -6239,6 +6237,7 @@ zfs_modevent(module_t mod, int type, void *unused __unused) tsd_destroy(&zfs_fsyncer_key); tsd_destroy(&rrw_tsd_key); + tsd_destroy(&zfs_allow_log_key); mutex_destroy(&zfs_share_lock); break; From 91edf3741445b733a5ea5fa8fe120504e38d1812 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Thu, 7 Mar 2013 23:45:16 +0000 Subject: [PATCH 06/17] Comment out unfeasible illumos copyin code and restore previous behavior. --- .../contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index 6ba9192d4a92..66b710d3366d 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -5853,6 +5853,7 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag, return (EINVAL); vec = &zfs_ioc_vec[vecnum]; +#ifdef illumos zc = kmem_zalloc(sizeof(zfs_cmd_t), KM_SLEEP); bzero(zc, sizeof(zfs_cmd_t)); @@ -5861,11 +5862,15 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag, error = EFAULT; goto out; } +#endif if (cflag != ZFS_CMD_COMPAT_NONE) { + zc = kmem_zalloc(sizeof(zfs_cmd_t), KM_SLEEP); + bzero(zc, sizeof(zfs_cmd_t)); zfs_cmd_compat_get(zc, arg, cflag); zfs_ioctl_compat_pre(zc, &vecnum, cflag); - } + } else + zc = (void *)arg; zc->zc_iflags = flag & FKIOCTL; if (zc->zc_nvlist_src_size != 0) { @@ -5983,9 +5988,12 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag, if (cflag != ZFS_CMD_COMPAT_NONE) { zfs_ioctl_compat_post(zc, cmd, cflag); zfs_cmd_compat_put(zc, arg, cflag); + kmem_free(zc, sizeof (zfs_cmd_t)); } +#ifdef illumos kmem_free(zc, sizeof (zfs_cmd_t)); +#endif return (error); } From 4f33cfb28418786e343f1ae8c9bd72c5dfb54d25 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Sat, 16 Mar 2013 20:28:38 +0000 Subject: [PATCH 07/17] Initialize "error" variable where illumos does. --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index 66b710d3366d..38c386e51880 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -5862,6 +5862,8 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag, error = EFAULT; goto out; } +#else + error = 0; #endif if (cflag != ZFS_CMD_COMPAT_NONE) { From e2b4467975f1ff37b165a76e9ad46c81894e98a6 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Sun, 17 Mar 2013 10:57:04 +0000 Subject: [PATCH 08/17] libzfs_core: - provide complete backwards compatibility (old utility, new kernel) - add zfs_cmd_t compatibility mapping in both directions - determine ioctl address in zfs_ioctl_compat.c --- .../lib/libzfs/common/libzfs_compat.h | 10 +- .../opensolaris/common/zfs/zfs_ioctl_compat.c | 258 ++++++++++++++++-- .../opensolaris/common/zfs/zfs_ioctl_compat.h | 50 +++- .../opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 23 +- 4 files changed, 314 insertions(+), 27 deletions(-) diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h index b6654b456c3a..881737d898a1 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h @@ -43,18 +43,18 @@ static int zfs_ioctl_version = 0; static __inline int zcmd_ioctl(int fd, int request, zfs_cmd_t *zc) { - unsigned long cmd; size_t oldsize, zfs_kernel_version_size, zfs_ioctl_version_size; int version, ret, cflag = ZFS_CMD_COMPAT_NONE; - cmd = _IOWR('Z', request, struct zfs_cmd); - zfs_ioctl_version_size = sizeof(zfs_ioctl_version); if (zfs_ioctl_version == 0) { sysctlbyname("vfs.zfs.version.ioctl", &zfs_ioctl_version, &zfs_ioctl_version_size, NULL, 0); } + if (zfs_ioctl_version == ZFS_IOCVER_DEADMAN) + cflag = ZFS_CMD_COMPAT_DEADMAN; + /* * If vfs.zfs.version.ioctl is not defined, assume we have v28 * compatible binaries and use vfs.zfs.version.spa to test for v15 @@ -76,7 +76,7 @@ zcmd_ioctl(int fd, int request, zfs_cmd_t *zc) } oldsize = zc->zc_nvlist_dst_size; - ret = zcmd_ioctl_compat(fd, cmd, zc, cflag); + ret = zcmd_ioctl_compat(fd, request, zc, cflag); if (ret == 0 && oldsize < zc->zc_nvlist_dst_size) { ret = -1; @@ -85,7 +85,7 @@ zcmd_ioctl(int fd, int request, zfs_cmd_t *zc) return (ret); } -#define ioctl(fd, cmd, zc) zcmd_ioctl((fd), (cmd), (zc)) +#define ioctl(fd, ioc, zc) zcmd_ioctl((fd), (ioc), (zc)) #ifdef __cplusplus } diff --git a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c index 0463e9a82bd1..926ba26dd130 100644 --- a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c +++ b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c @@ -33,6 +33,7 @@ #include #include #include +#include "zfs_namecheck.h" #include "zfs_ioctl_compat.h" static int zfs_version_ioctl = ZFS_IOCVER_CURRENT; @@ -49,8 +50,53 @@ zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_t addr, const int cflag) { zfs_cmd_v15_t *zc_c; zfs_cmd_v28_t *zc28_c; + zfs_cmd_deadman_t *zcdm_c; switch (cflag) { + case ZFS_CMD_COMPAT_DEADMAN: + zcdm_c = (void *)addr; + /* zc */ + strlcpy(zc->zc_name, zcdm_c->zc_name, MAXPATHLEN); + strlcpy(zc->zc_value, zcdm_c->zc_value, MAXPATHLEN * 2); + strlcpy(zc->zc_string, zcdm_c->zc_string, MAXPATHLEN); + strlcpy(zc->zc_top_ds, zcdm_c->zc_top_ds, MAXPATHLEN); + zc->zc_guid = zcdm_c->zc_guid; + zc->zc_nvlist_conf = zcdm_c->zc_nvlist_conf; + zc->zc_nvlist_conf_size = zcdm_c->zc_nvlist_conf_size; + zc->zc_nvlist_src = zcdm_c->zc_nvlist_src; + zc->zc_nvlist_src_size = zcdm_c->zc_nvlist_src_size; + zc->zc_nvlist_dst = zcdm_c->zc_nvlist_dst; + zc->zc_nvlist_dst_size = zcdm_c->zc_nvlist_dst_size; + zc->zc_cookie = zcdm_c->zc_cookie; + zc->zc_objset_type = zcdm_c->zc_objset_type; + zc->zc_perm_action = zcdm_c->zc_perm_action; + zc->zc_history = zcdm_c->zc_history; + zc->zc_history_len = zcdm_c->zc_history_len; + zc->zc_history_offset = zcdm_c->zc_history_offset; + zc->zc_obj = zcdm_c->zc_obj; + zc->zc_iflags = zcdm_c->zc_iflags; + zc->zc_share = zcdm_c->zc_share; + zc->zc_jailid = zcdm_c->zc_jailid; + zc->zc_objset_stats = zcdm_c->zc_objset_stats; + zc->zc_begin_record = zcdm_c->zc_begin_record; + zc->zc_defer_destroy = zcdm_c->zc_defer_destroy; + zc->zc_temphold = zcdm_c->zc_temphold; + zc->zc_action_handle = zcdm_c->zc_action_handle; + zc->zc_cleanup_fd = zcdm_c->zc_cleanup_fd; + zc->zc_simple = zcdm_c->zc_simple; + bcopy(zcdm_c->zc_pad, zc->zc_pad, sizeof(zc->zc_pad)); + zc->zc_sendobj = zcdm_c->zc_sendobj; + zc->zc_fromobj = zcdm_c->zc_fromobj; + zc->zc_createtxg = zcdm_c->zc_createtxg; + zc->zc_stat = zcdm_c->zc_stat; + + /* zc_inject_record doesn't change in libzfs_core */ + zcdm_c->zc_inject_record = zc->zc_inject_record; + + /* we always assume zc_nvlist_dst_filled is true */ + zc->zc_nvlist_dst_filled = B_TRUE; + break; + case ZFS_CMD_COMPAT_V28: zc28_c = (void *)addr; @@ -178,8 +224,51 @@ zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_t addr, const int cflag) { zfs_cmd_v15_t *zc_c; zfs_cmd_v28_t *zc28_c; + zfs_cmd_deadman_t *zcdm_c; switch (cflag) { + case ZFS_CMD_COMPAT_DEADMAN: + zcdm_c = (void *)addr; + + strlcpy(zcdm_c->zc_name, zc->zc_name, MAXPATHLEN); + strlcpy(zcdm_c->zc_value, zc->zc_value, MAXPATHLEN * 2); + strlcpy(zcdm_c->zc_string, zc->zc_string, MAXPATHLEN); + strlcpy(zcdm_c->zc_top_ds, zc->zc_top_ds, MAXPATHLEN); + zcdm_c->zc_guid = zc->zc_guid; + zcdm_c->zc_nvlist_conf = zc->zc_nvlist_conf; + zcdm_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size; + zcdm_c->zc_nvlist_src = zc->zc_nvlist_src; + zcdm_c->zc_nvlist_src_size = zc->zc_nvlist_src_size; + zcdm_c->zc_nvlist_dst = zc->zc_nvlist_dst; + zcdm_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size; + zcdm_c->zc_cookie = zc->zc_cookie; + zcdm_c->zc_objset_type = zc->zc_objset_type; + zcdm_c->zc_perm_action = zc->zc_perm_action; + zcdm_c->zc_history = zc->zc_history; + zcdm_c->zc_history_len = zc->zc_history_len; + zcdm_c->zc_history_offset = zc->zc_history_offset; + zcdm_c->zc_obj = zc->zc_obj; + zcdm_c->zc_iflags = zc->zc_iflags; + zcdm_c->zc_share = zc->zc_share; + zcdm_c->zc_jailid = zc->zc_jailid; + zcdm_c->zc_objset_stats = zc->zc_objset_stats; + zcdm_c->zc_begin_record = zc->zc_begin_record; + zcdm_c->zc_defer_destroy = zc->zc_defer_destroy; + zcdm_c->zc_temphold = zc->zc_temphold; + zcdm_c->zc_action_handle = zc->zc_action_handle; + zcdm_c->zc_cleanup_fd = zc->zc_cleanup_fd; + zcdm_c->zc_simple = zc->zc_simple; + bcopy(zc->zc_pad, zcdm_c->zc_pad, sizeof(zcdm_c->zc_pad)); + zcdm_c->zc_sendobj = zc->zc_sendobj; + zcdm_c->zc_fromobj = zc->zc_fromobj; + zcdm_c->zc_createtxg = zc->zc_createtxg; + zcdm_c->zc_stat = zc->zc_stat; + + /* zc_inject_record doesn't change in libzfs_core */ + zc->zc_inject_record = zcdm_c->zc_inject_record; + + break; + case ZFS_CMD_COMPAT_V28: zc28_c = (void *)addr; @@ -476,7 +565,7 @@ zfs_ioctl_compat_pool_get_props(zfs_cmd_t *zc) #ifndef _KERNEL int -zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag) +zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag) { int nc, ret; void *zc_c; @@ -484,16 +573,21 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag) switch (cflag) { case ZFS_CMD_COMPAT_NONE: - ret = ioctl(fd, cmd, zc); + ncmd = _IOWR('Z', request, struct zfs_cmd); + ret = ioctl(fd, ncmd, zc); return (ret); + case ZFS_CMD_COMPAT_DEADMAN: + zc_c = malloc(sizeof(zfs_cmd_deadman_t)); + ncmd = _IOWR('Z', request, struct zfs_cmd_deadman); + break; case ZFS_CMD_COMPAT_V28: zc_c = malloc(sizeof(zfs_cmd_v28_t)); - ncmd = _IOWR('Z', ZFS_IOCREQ(cmd), struct zfs_cmd_v28); + ncmd = _IOWR('Z', request, struct zfs_cmd_v28); break; case ZFS_CMD_COMPAT_V15: - nc = zfs_ioctl_v28_to_v15[ZFS_IOCREQ(cmd)]; + nc = zfs_ioctl_v28_to_v15[request]; zc_c = malloc(sizeof(zfs_cmd_v15_t)); - ncmd = _IOWR('Z', nc, struct zfs_cmd_v15); + ncmd = _IOWR('Z', request, struct zfs_cmd_v15); break; default: return (EINVAL); @@ -505,18 +599,18 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag) zfs_cmd_compat_put(zc, (caddr_t)zc_c, cflag); ret = ioctl(fd, ncmd, zc_c); if (cflag == ZFS_CMD_COMPAT_V15 && - nc == 2 /* ZFS_IOC_POOL_IMPORT */) - ret = ioctl(fd, _IOWR('Z', 4 /* ZFS_IOC_POOL_CONFIGS */, + nc == ZFS_IOC_POOL_IMPORT) + ret = ioctl(fd, _IOWR('Z', ZFS_IOC_POOL_CONFIGS, struct zfs_cmd_v15), zc_c); zfs_cmd_compat_get(zc, (caddr_t)zc_c, cflag); free(zc_c); if (cflag == ZFS_CMD_COMPAT_V15) { switch (nc) { - case 2: /* ZFS_IOC_POOL_IMPORT */ - case 4: /* ZFS_IOC_POOL_CONFIGS */ - case 5: /* ZFS_IOC_POOL_STATS */ - case 6: /* ZFS_IOC_POOL_TRYIMPORT */ + case ZFS_IOC_POOL_IMPORT: + case ZFS_IOC_POOL_CONFIGS: + case ZFS_IOC_POOL_STATS: + case ZFS_IOC_POOL_TRYIMPORT: zfs_ioctl_compat_fix_stats(zc, nc); break; case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */ @@ -528,16 +622,25 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag) return (ret); } #else /* _KERNEL */ -void +int zfs_ioctl_compat_pre(zfs_cmd_t *zc, int *vec, const int cflag) { - if (cflag == ZFS_CMD_COMPAT_V15) + int error = 0; + + /* are we creating a clone? */ + if (*vec == ZFS_IOC_CREATE && zc->zc_value[0] != '\0') + *vec = ZFS_IOC_CLONE; + + if (cflag == ZFS_CMD_COMPAT_V15) { switch (*vec) { case 7: /* ZFS_IOC_POOL_SCRUB (v15) */ zc->zc_cookie = POOL_SCAN_SCRUB; break; } + } + + return (error); } void @@ -545,9 +648,9 @@ zfs_ioctl_compat_post(zfs_cmd_t *zc, int vec, const int cflag) { if (cflag == ZFS_CMD_COMPAT_V15) { switch (vec) { - case 4: /* ZFS_IOC_POOL_CONFIGS */ - case 5: /* ZFS_IOC_POOL_STATS */ - case 6: /* ZFS_IOC_POOL_TRYIMPORT */ + case ZFS_IOC_POOL_CONFIGS: + case ZFS_IOC_POOL_STATS: + case ZFS_IOC_POOL_TRYIMPORT: zfs_ioctl_compat_fix_stats(zc, vec); break; case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */ @@ -556,4 +659,127 @@ zfs_ioctl_compat_post(zfs_cmd_t *zc, int vec, const int cflag) } } } + +nvlist_t * +zfs_ioctl_compat_innvl(zfs_cmd_t *zc, nvlist_t * innvl, const int vec, + const int cflag) +{ + nvlist_t *nvl, *tmpnvl; + char *poolname, *snapname; + int err; + + if (cflag == ZFS_CMD_COMPAT_NONE) + goto out; + + switch (vec) { + case ZFS_IOC_CREATE: + nvl = fnvlist_alloc(); + fnvlist_add_int32(nvl, "type", zc->zc_objset_type); + if (innvl != NULL) { + fnvlist_add_nvlist(nvl, "props", innvl); + nvlist_free(innvl); + } + return (nvl); + break; + case ZFS_IOC_CLONE: + nvl = fnvlist_alloc(); + fnvlist_add_string(nvl, "origin", zc->zc_value); + if (innvl != NULL) { + fnvlist_add_nvlist(nvl, "props", innvl); + nvlist_free(innvl); + } + return (nvl); + break; + case ZFS_IOC_SNAPSHOT: + if (innvl == NULL) + goto out; + nvl = fnvlist_alloc(); + fnvlist_add_nvlist(nvl, "props", innvl); + tmpnvl = fnvlist_alloc(); + snapname = kmem_asprintf("%s@%s", zc->zc_name, zc->zc_value); + fnvlist_add_boolean(tmpnvl, snapname); + kmem_free(snapname, strlen(snapname + 1)); + /* check if we are doing a recursive snapshot */ + if (zc->zc_cookie) + dmu_get_recursive_snaps_nvl(zc->zc_name, zc->zc_value, + tmpnvl); + fnvlist_add_nvlist(nvl, "snaps", tmpnvl); + fnvlist_free(tmpnvl); + nvlist_free(innvl); + /* strip dataset part from zc->zc_name */ + zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0'; + return (nvl); + break; + case ZFS_IOC_SPACE_SNAPS: + nvl = fnvlist_alloc(); + fnvlist_add_string(nvl, "firstsnap", zc->zc_value); + if (innvl != NULL) + nvlist_free(innvl); + return (nvl); + break; + case ZFS_IOC_DESTROY_SNAPS: + if (innvl == NULL && cflag == ZFS_CMD_COMPAT_DEADMAN) + goto out; + nvl = fnvlist_alloc(); + if (innvl != NULL) { + fnvlist_add_nvlist(nvl, "snaps", innvl); + } else { + /* + * We are probably called by even older binaries, + * allocate and populate nvlist with recursive + * snapshots + */ + if (snapshot_namecheck(zc->zc_value, NULL, + NULL) == 0) { + tmpnvl = fnvlist_alloc(); + if (dmu_get_recursive_snaps_nvl(zc->zc_name, + zc->zc_value, tmpnvl) == 0) + fnvlist_add_nvlist(nvl, "snaps", + tmpnvl); + nvlist_free(tmpnvl); + } + } + if (innvl != NULL) + nvlist_free(innvl); + /* strip dataset part from zc->zc_name */ + zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0'; + return (nvl); + break; + } +out: + return (innvl); +} + +nvlist_t * +zfs_ioctl_compat_outnvl(zfs_cmd_t *zc, nvlist_t * outnvl, const int vec, + const int cflag) +{ + nvlist_t *tmpnvl; + + if (cflag == ZFS_CMD_COMPAT_NONE) + return (outnvl); + + switch (vec) { + case ZFS_IOC_SPACE_SNAPS: + (void) nvlist_lookup_uint64(outnvl, "used", &zc->zc_cookie); + (void) nvlist_lookup_uint64(outnvl, "compressed", + &zc->zc_objset_type); + (void) nvlist_lookup_uint64(outnvl, "uncompressed", + &zc->zc_perm_action); + nvlist_free(outnvl); + /* return empty outnvl */ + tmpnvl = fnvlist_alloc(); + return (tmpnvl); + break; + case ZFS_IOC_CREATE: + case ZFS_IOC_CLONE: + nvlist_free(outnvl); + /* return empty outnvl */ + tmpnvl = fnvlist_alloc(); + return (tmpnvl); + break; + } + + return (outnvl); +} #endif /* KERNEL */ diff --git a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h index 6e897b8fbc01..2ec2242321b6 100644 --- a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h +++ b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h @@ -45,13 +45,15 @@ extern "C" { */ /* ioctl versions for vfs.zfs.version.ioctl */ +#define ZFS_IOCVER_LZC 2 #define ZFS_IOCVER_DEADMAN 1 -#define ZFS_IOCVER_CURRENT ZFS_IOCVER_DEADMAN +#define ZFS_IOCVER_CURRENT ZFS_IOCVER_LZC /* 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_IOC_COMPAT_PASS 254 #define ZFS_IOC_COMPAT_FAIL 255 @@ -150,6 +152,44 @@ typedef struct zfs_cmd_v28 { zfs_stat_t zc_stat; } zfs_cmd_v28_t; +typedef struct zfs_cmd_deadman { + char zc_name[MAXPATHLEN]; + char zc_value[MAXPATHLEN * 2]; + char zc_string[MAXNAMELEN]; + char zc_top_ds[MAXPATHLEN]; + uint64_t zc_guid; + uint64_t zc_nvlist_conf; /* really (char *) */ + uint64_t zc_nvlist_conf_size; + 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; + uint64_t zc_cookie; + uint64_t zc_objset_type; + uint64_t zc_perm_action; + uint64_t zc_history; /* really (char *) */ + 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; + struct drr_begin zc_begin_record; + /* zc_inject_record doesn't change in libzfs_core */ + zinject_record_t zc_inject_record; + boolean_t zc_defer_destroy; + boolean_t zc_temphold; + uint64_t zc_action_handle; + int zc_cleanup_fd; + uint8_t zc_simple; + uint8_t zc_pad[3]; /* alignment */ + uint64_t zc_sendobj; + uint64_t zc_fromobj; + uint64_t zc_createtxg; + zfs_stat_t zc_stat; +} zfs_cmd_deadman_t; + #ifdef _KERNEL unsigned static long zfs_ioctl_v15_to_v28[] = { 0, /* 0 ZFS_IOC_POOL_CREATE */ @@ -274,10 +314,14 @@ unsigned static long zfs_ioctl_v28_to_v15[] = { #endif /* ! _KERNEL */ #ifdef _KERNEL -void zfs_ioctl_compat_pre(zfs_cmd_t *, int *, const int); +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); #else -int zcmd_ioctl_compat(int, unsigned long, zfs_cmd_t *, const int); +int zcmd_ioctl_compat(int, int, zfs_cmd_t *, const int); #endif /* _KERNEL */ void zfs_cmd_compat_get(zfs_cmd_t *, caddr_t, const int); void zfs_cmd_compat_put(zfs_cmd_t *, caddr_t, const int); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index 38c386e51880..bb2ead38e495 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -5805,7 +5805,7 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag, #ifdef illumos minor_t minor = getminor(dev); #else - int cflag, cmd; + int cflag, cmd, oldvecnum; cred_t *cr = td->td_ucred; #endif const zfs_ioc_vec_t *vec; @@ -5821,7 +5821,10 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag, * and translate zfs_cmd if necessary */ if (len < sizeof(zfs_cmd_t)) - if (len == sizeof(zfs_cmd_v28_t)) { + if (len == sizeof(zfs_cmd_deadman_t)) { + cflag = ZFS_CMD_COMPAT_DEADMAN; + vecnum = cmd; + } else if (len == sizeof(zfs_cmd_v28_t)) { cflag = ZFS_CMD_COMPAT_V28; vecnum = cmd; } else if (len == sizeof(zfs_cmd_v15_t)) { @@ -5870,7 +5873,12 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag, zc = kmem_zalloc(sizeof(zfs_cmd_t), KM_SLEEP); bzero(zc, sizeof(zfs_cmd_t)); zfs_cmd_compat_get(zc, arg, cflag); - zfs_ioctl_compat_pre(zc, &vecnum, cflag); + oldvecnum = vecnum; + error = zfs_ioctl_compat_pre(zc, &vecnum, cflag); + if (error != 0) + goto out; + if (oldvecnum != vecnum) + vec = &zfs_ioc_vec[vecnum]; } else zc = (void *)arg; @@ -5882,6 +5890,10 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag, goto out; } + /* rewrite innvl for backwards compatibility */ + if (cflag != ZFS_CMD_COMPAT_NONE) + innvl = zfs_ioctl_compat_innvl(zc, innvl, vecnum, cflag); + /* * Ensure that all pool/dataset names are valid before we pass down to * the lower layers. @@ -5955,6 +5967,11 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag, } fnvlist_free(lognv); + /* rewrite outnvl for backwards compatibility */ + if (cflag != ZFS_CMD_COMPAT_NONE) + outnvl = zfs_ioctl_compat_outnvl(zc, outnvl, vecnum, + cflag); + if (!nvlist_empty(outnvl) || zc->zc_nvlist_dst_size != 0) { int smusherror = 0; if (vec->zvec_smush_outnvlist) { From 70b0720877242f967367c930630d5a6ea0d99e7e Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Sun, 17 Mar 2013 17:28:06 +0000 Subject: [PATCH 09/17] Fix accidentially changed ioc variable for old v15 compatibility --- sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c index 926ba26dd130..f0318b0b2001 100644 --- a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c +++ b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c @@ -587,7 +587,7 @@ zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag) case ZFS_CMD_COMPAT_V15: nc = zfs_ioctl_v28_to_v15[request]; zc_c = malloc(sizeof(zfs_cmd_v15_t)); - ncmd = _IOWR('Z', request, struct zfs_cmd_v15); + ncmd = _IOWR('Z', nc, struct zfs_cmd_v15); break; default: return (EINVAL); From 67ebc12d497009f61cb7fce77270a785c56c695e Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Sun, 17 Mar 2013 18:33:06 +0000 Subject: [PATCH 10/17] Add forwards compatibility for libzfs_core Unsupported: creation of multiple snapshots including "zfs snapshot -r" --- .../lib/libzfs_core/common/libzfs_core.c | 33 ++++- .../lib/libzfs_core/common/libzfs_core.h | 3 + .../libzfs_core/common/libzfs_core_compat.c | 134 ++++++++++++++++++ .../libzfs_core/common/libzfs_core_compat.h | 47 ++++++ cddl/lib/libzfs_core/Makefile | 2 +- 5 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c create mode 100644 cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.h diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c index b6c28bee01ab..c8b401e2f612 100644 --- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c @@ -86,6 +86,10 @@ #include #include +#ifdef __FreeBSD__ +extern int zfs_ioctl_version; +#endif + static int g_fd; static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER; static int g_refcount; @@ -124,12 +128,24 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name, zfs_cmd_t zc = { 0 }; int error = 0; char *packed; +#ifdef __FreeBSD__ + nvlist_t *oldsource; +#endif size_t size; ASSERT3S(g_refcount, >, 0); (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); +#ifdef __FreeBSD__ + if (zfs_ioctl_version < ZFS_IOCVER_LZC) { + oldsource = source; + error = lzc_compat_pre(&zc, &ioc, &source); + if (error) + return (error); + } +#endif + packed = fnvlist_pack(source, &size); zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed; zc.zc_nvlist_src_size = size; @@ -167,14 +183,29 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name, break; } } + +#ifdef __FreeBSD__ + if (zfs_ioctl_version < ZFS_IOCVER_LZC) + lzc_compat_post(&zc, ioc); +#endif if (zc.zc_nvlist_dst_filled) { *resultp = fnvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst, zc.zc_nvlist_dst_size); } else if (resultp != NULL) { *resultp = NULL; } - +#ifdef __FreeBSD__ + if (zfs_ioctl_version < ZFS_IOCVER_LZC) + lzc_compat_outnvl(&zc, ioc, resultp); +#endif out: +#ifdef __FreeBSD__ + if (zfs_ioctl_version < ZFS_IOCVER_LZC) { + if (source != oldsource) + nvlist_free(source); + source = oldsource; + } +#endif fnvlist_pack_free(packed, size); free((void *)(uintptr_t)zc.zc_nvlist_dst); return (error); diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h index c8bfbefbdaf5..ee19d17af24f 100644 --- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h @@ -31,6 +31,9 @@ #include #include #include +#ifdef __FreeBSD__ +#include "libzfs_core_compat.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c new file mode 100644 index 000000000000..e5eb7aeacc6f --- /dev/null +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c @@ -0,0 +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 http://www.opensolaris.org/os/licensing. + * 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) 2013 Martin Matuska . All rights reserved. + */ + +#include +#include + +extern int zfs_ioctl_version; + +int +lzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source) +{ + nvlist_t *nvl = NULL; + nvpair_t *pair; + char *buf; + zfs_ioc_t vecnum; + uint32_t type32; + int error = 0; + int pos; + + if (zfs_ioctl_version >= ZFS_IOCVER_LZC) + return (0); + + vecnum = *ioc; + + switch (vecnum) { + case ZFS_IOC_CREATE: + type32 = fnvlist_lookup_int32(*source, "type"); + zc->zc_objset_type = (uint64_t)type32; + nvlist_lookup_nvlist(*source, "props", &nvl); + *source = nvl; + break; + case ZFS_IOC_CLONE: + buf = fnvlist_lookup_string(*source, "origin"); + strlcpy(zc->zc_value, buf, MAXPATHLEN); + nvlist_lookup_nvlist(*source, "props", &nvl); + *ioc = ZFS_IOC_CREATE; + *source = nvl; + break; + case ZFS_IOC_SNAPSHOT: + nvl = fnvlist_lookup_nvlist(*source, "snaps"); + pair = nvlist_next_nvpair(nvl, NULL); + if (pair != NULL) { + buf = nvpair_name(pair); + pos = strcspn(buf, "@"); + strlcpy(zc->zc_name, buf, pos + 1); + strlcpy(zc->zc_value, buf + pos + 1, MAXPATHLEN); + } else + error = EOPNOTSUPP; + /* old kernel cannot create multiple snapshots */ + if (!error && nvlist_next_nvpair(nvl, pair) != NULL) + error = EOPNOTSUPP; + nvlist_free(nvl); + nvl = NULL; + nvlist_lookup_nvlist(*source, "props", &nvl); + *source = nvl; + break; + case ZFS_IOC_SPACE_SNAPS: + buf = fnvlist_lookup_string(*source, "firstsnap"); + strlcpy(zc->zc_value, buf, MAXPATHLEN); + break; + case ZFS_IOC_DESTROY_SNAPS: + nvl = fnvlist_lookup_nvlist(*source, "snaps"); + pair = nvlist_next_nvpair(nvl, NULL); + if (pair != NULL) { + buf = nvpair_name(pair); + pos = strcspn(buf, "@"); + strlcpy(zc->zc_name, buf, pos + 1); + } + *source = nvl; + break; + } + + return (error); +} + +void +lzc_compat_post(zfs_cmd_t *zc, const zfs_ioc_t ioc) +{ + if (zfs_ioctl_version >= ZFS_IOCVER_LZC) + return; + + switch (ioc) { + case ZFS_IOC_CREATE: + case ZFS_IOC_CLONE: + case ZFS_IOC_SNAPSHOT: + case ZFS_IOC_SPACE_SNAPS: + case ZFS_IOC_DESTROY_SNAPS: + zc->zc_nvlist_dst_filled = B_FALSE; + break; + } +} + +int +lzc_compat_outnvl(zfs_cmd_t *zc, const zfs_ioc_t ioc, nvlist_t **outnvl) +{ + nvlist_t *nvl; + + if (zfs_ioctl_version >= ZFS_IOCVER_LZC) + return (0); + + switch (ioc) { + case ZFS_IOC_SPACE_SNAPS: + nvl = fnvlist_alloc(); + fnvlist_add_uint64(nvl, "used", zc->zc_cookie); + fnvlist_add_uint64(nvl, "compressed", zc->zc_objset_type); + fnvlist_add_uint64(nvl, "uncompressed", zc->zc_perm_action); + *outnvl = nvl; + break; + } + + return (0); +} diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.h b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.h new file mode 100644 index 000000000000..6527c4b2576f --- /dev/null +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.h @@ -0,0 +1,47 @@ +/* + * 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 http://www.opensolaris.org/os/licensing. + * 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) 2013 by Martin Matuska . All rights reserved. + */ + +#ifndef _LIBZFS_CORE_COMPAT_H +#define _LIBZFS_CORE_COMPAT_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int lzc_compat_pre(zfs_cmd_t *, zfs_ioc_t *, nvlist_t **); +void lzc_compat_post(zfs_cmd_t *, const zfs_ioc_t); +int lzc_compat_outnvl(zfs_cmd_t *, const zfs_ioc_t, nvlist_t **); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBZFS_CORE_COMPAT_H */ diff --git a/cddl/lib/libzfs_core/Makefile b/cddl/lib/libzfs_core/Makefile index 5f2fc5703c92..d0993689dd27 100644 --- a/cddl/lib/libzfs_core/Makefile +++ b/cddl/lib/libzfs_core/Makefile @@ -9,7 +9,7 @@ LIB= zfs_core DPADD= ${LIBNVPAIR} LDADD= -lnvpair -SRCS= libzfs_core.c +SRCS= libzfs_core.c libzfs_core_compat.c WARNS?= 0 CSTD= c99 From af2e40ccd1ca76b646750f248ef7d05f221c9d02 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Sun, 17 Mar 2013 18:49:11 +0000 Subject: [PATCH 11/17] Merge libzfs_core part of r239388 Illumos ZFS issues: 3085 zfs diff panics, then panics in a loop on booting References: https://www.illumos.org/issues/3085 --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c index 15d3050c6362..0fe5f7165c89 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c @@ -444,8 +444,10 @@ log_internal(nvlist_t *nvl, const char *operation, spa_t *spa, * initialized yet, so don't bother logging the internal events. * Likewise if the pool is not writeable. */ - if (tx->tx_txg == TXG_INITIAL || !spa_writeable(spa)) + if (tx->tx_txg == TXG_INITIAL || !spa_writeable(spa)) { + fnvlist_free(nvl); return; + } va_copy(adx2, adx); From d97b41582d8f4603222358f33b73d378388c3778 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Sun, 17 Mar 2013 22:24:08 +0000 Subject: [PATCH 12/17] Fix working with zfs_ioctl_version in libzfs_compat.h and include mirror lzc_ioctl_version in libzfs_core --- .../lib/libzfs/common/libzfs_compat.h | 26 ++++++++++++++----- .../lib/libzfs_core/common/libzfs_core.c | 17 +++++++----- .../lib/libzfs_core/common/libzfs_core.h | 3 --- .../libzfs_core/common/libzfs_core_compat.c | 11 ++++---- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h index 881737d898a1..400c81443be9 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h @@ -32,8 +32,23 @@ extern "C" { #endif +static int zfs_ioctl_version = -1; static int zfs_kernel_version = 0; -static int zfs_ioctl_version = 0; + +/* + * Get zfs_ioctl_version + */ +static __inline int +get_zfs_ioctl_version(void) +{ + size_t ver_size; + int ver = 0; + + ver_size = sizeof(ver); + sysctlbyname("vfs.zfs.version.ioctl", &ver, &ver_size, NULL, 0); + + return (ver); +} /* * This is FreeBSD version of ioctl, because Solaris' ioctl() updates @@ -43,14 +58,11 @@ static int zfs_ioctl_version = 0; static __inline int zcmd_ioctl(int fd, int request, zfs_cmd_t *zc) { - size_t oldsize, zfs_kernel_version_size, zfs_ioctl_version_size; + size_t oldsize, zfs_kernel_version_size; int version, ret, cflag = ZFS_CMD_COMPAT_NONE; - zfs_ioctl_version_size = sizeof(zfs_ioctl_version); - if (zfs_ioctl_version == 0) { - sysctlbyname("vfs.zfs.version.ioctl", &zfs_ioctl_version, - &zfs_ioctl_version_size, NULL, 0); - } + if (zfs_ioctl_version == -1) + zfs_ioctl_version = get_zfs_ioctl_version(); if (zfs_ioctl_version == ZFS_IOCVER_DEADMAN) cflag = ZFS_CMD_COMPAT_DEADMAN; diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c index c8b401e2f612..3319d20e7c72 100644 --- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c @@ -84,10 +84,11 @@ #include #include #include -#include +#include "libzfs_core_compat.h" +#include "libzfs_compat.h" #ifdef __FreeBSD__ -extern int zfs_ioctl_version; +int lzc_ioctl_version = -1; #endif static int g_fd; @@ -107,6 +108,7 @@ libzfs_core_init(void) } g_refcount++; (void) pthread_mutex_unlock(&g_lock); + return (0); } @@ -138,7 +140,10 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name, (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); #ifdef __FreeBSD__ - if (zfs_ioctl_version < ZFS_IOCVER_LZC) { + if (lzc_ioctl_version == -1) + lzc_ioctl_version = get_zfs_ioctl_version(); + + if (lzc_ioctl_version < ZFS_IOCVER_LZC) { oldsource = source; error = lzc_compat_pre(&zc, &ioc, &source); if (error) @@ -185,7 +190,7 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name, } #ifdef __FreeBSD__ - if (zfs_ioctl_version < ZFS_IOCVER_LZC) + if (lzc_ioctl_version < ZFS_IOCVER_LZC) lzc_compat_post(&zc, ioc); #endif if (zc.zc_nvlist_dst_filled) { @@ -195,12 +200,12 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name, *resultp = NULL; } #ifdef __FreeBSD__ - if (zfs_ioctl_version < ZFS_IOCVER_LZC) + if (lzc_ioctl_version < ZFS_IOCVER_LZC) lzc_compat_outnvl(&zc, ioc, resultp); #endif out: #ifdef __FreeBSD__ - if (zfs_ioctl_version < ZFS_IOCVER_LZC) { + if (lzc_ioctl_version < ZFS_IOCVER_LZC) { if (source != oldsource) nvlist_free(source); source = oldsource; diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h index ee19d17af24f..c8bfbefbdaf5 100644 --- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h @@ -31,9 +31,6 @@ #include #include #include -#ifdef __FreeBSD__ -#include "libzfs_core_compat.h" -#endif #ifdef __cplusplus extern "C" { diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c index e5eb7aeacc6f..0ab12b627f78 100644 --- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c @@ -24,9 +24,10 @@ */ #include -#include +#include +#include "libzfs_core_compat.h" -extern int zfs_ioctl_version; +extern int lzc_ioctl_version; int lzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source) @@ -39,7 +40,7 @@ lzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source) int error = 0; int pos; - if (zfs_ioctl_version >= ZFS_IOCVER_LZC) + if (lzc_ioctl_version >= ZFS_IOCVER_LZC) return (0); vecnum = *ioc; @@ -98,7 +99,7 @@ lzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source) void lzc_compat_post(zfs_cmd_t *zc, const zfs_ioc_t ioc) { - if (zfs_ioctl_version >= ZFS_IOCVER_LZC) + if (lzc_ioctl_version >= ZFS_IOCVER_LZC) return; switch (ioc) { @@ -117,7 +118,7 @@ lzc_compat_outnvl(zfs_cmd_t *zc, const zfs_ioc_t ioc, nvlist_t **outnvl) { nvlist_t *nvl; - if (zfs_ioctl_version >= ZFS_IOCVER_LZC) + if (lzc_ioctl_version >= ZFS_IOCVER_LZC) return (0); switch (ioc) { From 6f4accc2de2112c732da5eafed194fa3cbf9ce96 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Mon, 18 Mar 2013 09:32:29 +0000 Subject: [PATCH 13/17] Move common zfs ioctl compatibility functions (userland) into libzfs_compat.c Introduce additional constants for zfs ioctl versions --- .../lib/libzfs/common/libzfs_compat.c | 103 ++++++++++++++++++ .../lib/libzfs/common/libzfs_compat.h | 66 +---------- .../lib/libzfs_core/common/libzfs_core.c | 14 +-- .../libzfs_core/common/libzfs_core_compat.c | 8 +- cddl/lib/libzfs/Makefile | 1 + cddl/lib/libzfs_core/Makefile | 6 +- .../opensolaris/common/zfs/zfs_ioctl_compat.h | 4 +- 7 files changed, 125 insertions(+), 77 deletions(-) create mode 100644 cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c new file mode 100644 index 000000000000..2a2ae761bd05 --- /dev/null +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c @@ -0,0 +1,103 @@ +/* + * CDDL HEADER SART + * + * 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 http://www.opensolaris.org/os/licensing. + * 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) 2013 Martin Matuska . All rights reserved. + */ + +#include "libzfs_compat.h" + +int zfs_ioctl_version = ZFS_IOCVER_UNDEF; +static int zfs_spa_version = -1; + +/* + * Get zfs_ioctl_version + */ +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); +} + +/* + * Get the SPA version + */ +static int +get_zfs_spa_version(void) +{ + size_t ver_size; + int ver = 0; + + ver_size = sizeof(ver); + sysctlbyname("vfs.zfs.version.spa", &ver, &ver_size, NULL, 0); + + return (ver); +} + +/* + * 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 +zcmd_ioctl(int fd, int 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(); + + if (zfs_ioctl_version == ZFS_IOCVER_DEADMAN) + cflag = ZFS_CMD_COMPAT_DEADMAN; + + /* + * If vfs.zfs.version.ioctl is not defined, assume we have v28 + * compatible binaries and use vfs.zfs.version.spa to test for v15 + */ + if (zfs_ioctl_version < ZFS_IOCVER_DEADMAN) { + cflag = ZFS_CMD_COMPAT_V28; + + if (zfs_spa_version < 0) + zfs_spa_version = get_zfs_spa_version(); + + if (zfs_spa_version == SPA_VERSION_15 || + zfs_spa_version == SPA_VERSION_14 || + zfs_spa_version == SPA_VERSION_13) + cflag = ZFS_CMD_COMPAT_V15; + } + + 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/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h index 400c81443be9..37616683330a 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h @@ -32,71 +32,9 @@ extern "C" { #endif -static int zfs_ioctl_version = -1; -static int zfs_kernel_version = 0; +int get_zfs_ioctl_version(void); +int zcmd_ioctl(int fd, int request, zfs_cmd_t *zc); -/* - * Get zfs_ioctl_version - */ -static __inline int -get_zfs_ioctl_version(void) -{ - size_t ver_size; - int ver = 0; - - ver_size = sizeof(ver); - sysctlbyname("vfs.zfs.version.ioctl", &ver, &ver_size, NULL, 0); - - return (ver); -} - -/* - * 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. - */ -static __inline int -zcmd_ioctl(int fd, int request, zfs_cmd_t *zc) -{ - size_t oldsize, zfs_kernel_version_size; - int version, ret, cflag = ZFS_CMD_COMPAT_NONE; - - if (zfs_ioctl_version == -1) - zfs_ioctl_version = get_zfs_ioctl_version(); - - if (zfs_ioctl_version == ZFS_IOCVER_DEADMAN) - cflag = ZFS_CMD_COMPAT_DEADMAN; - - /* - * If vfs.zfs.version.ioctl is not defined, assume we have v28 - * compatible binaries and use vfs.zfs.version.spa to test for v15 - */ - if (zfs_ioctl_version < ZFS_IOCVER_DEADMAN) { - cflag = ZFS_CMD_COMPAT_V28; - zfs_kernel_version_size = sizeof(zfs_kernel_version); - - if (zfs_kernel_version == 0) { - sysctlbyname("vfs.zfs.version.spa", - &zfs_kernel_version, - &zfs_kernel_version_size, NULL, 0); - } - - if (zfs_kernel_version == SPA_VERSION_15 || - zfs_kernel_version == SPA_VERSION_14 || - zfs_kernel_version == SPA_VERSION_13) - cflag = ZFS_CMD_COMPAT_V15; - } - - 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); -} #define ioctl(fd, ioc, zc) zcmd_ioctl((fd), (ioc), (zc)) #ifdef __cplusplus diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c index 3319d20e7c72..83d0296edf41 100644 --- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c @@ -88,7 +88,7 @@ #include "libzfs_compat.h" #ifdef __FreeBSD__ -int lzc_ioctl_version = -1; +extern int zfs_ioctl_version; #endif static int g_fd; @@ -140,10 +140,10 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name, (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); #ifdef __FreeBSD__ - if (lzc_ioctl_version == -1) - lzc_ioctl_version = get_zfs_ioctl_version(); + if (zfs_ioctl_version == ZFS_IOCVER_UNDEF) + zfs_ioctl_version = get_zfs_ioctl_version(); - if (lzc_ioctl_version < ZFS_IOCVER_LZC) { + if (zfs_ioctl_version < ZFS_IOCVER_LZC) { oldsource = source; error = lzc_compat_pre(&zc, &ioc, &source); if (error) @@ -190,7 +190,7 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name, } #ifdef __FreeBSD__ - if (lzc_ioctl_version < ZFS_IOCVER_LZC) + if (zfs_ioctl_version < ZFS_IOCVER_LZC) lzc_compat_post(&zc, ioc); #endif if (zc.zc_nvlist_dst_filled) { @@ -200,12 +200,12 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name, *resultp = NULL; } #ifdef __FreeBSD__ - if (lzc_ioctl_version < ZFS_IOCVER_LZC) + if (zfs_ioctl_version < ZFS_IOCVER_LZC) lzc_compat_outnvl(&zc, ioc, resultp); #endif out: #ifdef __FreeBSD__ - if (lzc_ioctl_version < ZFS_IOCVER_LZC) { + if (zfs_ioctl_version < ZFS_IOCVER_LZC) { if (source != oldsource) nvlist_free(source); source = oldsource; diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c index 0ab12b627f78..c19be1f99fc9 100644 --- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c @@ -27,7 +27,7 @@ #include #include "libzfs_core_compat.h" -extern int lzc_ioctl_version; +extern int zfs_ioctl_version; int lzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source) @@ -40,7 +40,7 @@ lzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source) int error = 0; int pos; - if (lzc_ioctl_version >= ZFS_IOCVER_LZC) + if (zfs_ioctl_version >= ZFS_IOCVER_LZC) return (0); vecnum = *ioc; @@ -99,7 +99,7 @@ lzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source) void lzc_compat_post(zfs_cmd_t *zc, const zfs_ioc_t ioc) { - if (lzc_ioctl_version >= ZFS_IOCVER_LZC) + if (zfs_ioctl_version >= ZFS_IOCVER_LZC) return; switch (ioc) { @@ -118,7 +118,7 @@ lzc_compat_outnvl(zfs_cmd_t *zc, const zfs_ioc_t ioc, nvlist_t **outnvl) { nvlist_t *nvl; - if (lzc_ioctl_version >= ZFS_IOCVER_LZC) + if (zfs_ioctl_version >= ZFS_IOCVER_LZC) return (0); switch (ioc) { diff --git a/cddl/lib/libzfs/Makefile b/cddl/lib/libzfs/Makefile index 7397cae4a6cf..5b6b47dcc28c 100644 --- a/cddl/lib/libzfs/Makefile +++ b/cddl/lib/libzfs/Makefile @@ -18,6 +18,7 @@ SRCS= deviceid.c \ zone.c SRCS+= libzfs_changelist.c \ + libzfs_compat.c \ libzfs_config.c \ libzfs_dataset.c \ libzfs_diff.c \ diff --git a/cddl/lib/libzfs_core/Makefile b/cddl/lib/libzfs_core/Makefile index d0993689dd27..a470fbc25fb1 100644 --- a/cddl/lib/libzfs_core/Makefile +++ b/cddl/lib/libzfs_core/Makefile @@ -4,12 +4,16 @@ .PATH: ${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/zfs .PATH: ${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/fs/zfs .PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs_core/common +.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs/common LIB= zfs_core DPADD= ${LIBNVPAIR} LDADD= -lnvpair -SRCS= libzfs_core.c libzfs_core_compat.c +SRCS= libzfs_core.c \ + libzfs_core_compat.c + +SRCS+= libzfs_compat.c WARNS?= 0 CSTD= c99 diff --git a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h index 2ec2242321b6..57c2909fcfb4 100644 --- a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h +++ b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h @@ -45,8 +45,10 @@ extern "C" { */ /* ioctl versions for vfs.zfs.version.ioctl */ -#define ZFS_IOCVER_LZC 2 +#define ZFS_IOCVER_UNDEF -1 +#define ZFS_IOCVER_NONE 0 #define ZFS_IOCVER_DEADMAN 1 +#define ZFS_IOCVER_LZC 2 #define ZFS_IOCVER_CURRENT ZFS_IOCVER_LZC /* compatibility conversion flag */ From a602517b63f9b6619d3bd47d380023832039aade Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Mon, 18 Mar 2013 20:22:40 +0000 Subject: [PATCH 14/17] Add missing zvol_create_mirrors() on zfs_ioc_create() --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index bb2ead38e495..96c4ec896a7e 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -3268,6 +3268,10 @@ zfs_ioc_create(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl) if (error != 0) (void) dmu_objset_destroy(fsname, B_FALSE); } +#ifdef __FreeBSD__ + if (error == 0 && type == DMU_OST_ZVOL) + zvol_create_minors(fsname); +#endif return (error); } From e56718d7343886f7a73eee1dd44fa3a1f597ae5b Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Tue, 19 Mar 2013 22:14:50 +0000 Subject: [PATCH 15/17] Run zvol_create_minors() on snapshot creation --- .../contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c index aee54076f366..d22432601fa9 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c @@ -1287,6 +1287,15 @@ dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors) fnvlist_free(suspended); } +#ifdef __FreeBSD__ +#ifdef _KERNEL + for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL; + pair = nvlist_next_nvpair(snaps, pair)) { + char *snapname = nvpair_name(pair); + zvol_create_minors(snapname); + } +#endif +#endif return (error); } From a0abc0d302570174e915d16dab1ffc1775973a72 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Tue, 19 Mar 2013 22:27:15 +0000 Subject: [PATCH 16/17] Run zvol_create_minors() only if in non-error case --- .../opensolaris/uts/common/fs/zfs/dsl_dataset.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c index d22432601fa9..1a6a06070d82 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c @@ -1289,10 +1289,12 @@ dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors) #ifdef __FreeBSD__ #ifdef _KERNEL - for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL; - pair = nvlist_next_nvpair(snaps, pair)) { - char *snapname = nvpair_name(pair); - zvol_create_minors(snapname); + if (error == 0) { + for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL; + pair = nvlist_next_nvpair(snaps, pair)) { + char *snapname = nvpair_name(pair); + zvol_create_minors(snapname); + } } #endif #endif From 192d5475742aab4b03f357cbe1dce11bdabfa215 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Wed, 20 Mar 2013 09:56:20 +0000 Subject: [PATCH 17/17] Release hold on pool before calling zvol_create_minor() --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c index 4e54abc19141..659805d1702f 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c @@ -2233,13 +2233,16 @@ zvol_create_minors(const char *name) return (error); } if (dmu_objset_type(os) == DMU_OST_ZVOL) { + dsl_dataset_long_hold(os->os_dsl_dataset, FTAG); + dsl_pool_rele(dmu_objset_pool(os), FTAG); if ((error = zvol_create_minor(name)) == 0) error = zvol_create_snapshots(os, name); else { printf("ZFS WARNING: Unable to create ZVOL %s (error=%d).\n", name, error); } - dmu_objset_rele(os, FTAG); + dsl_dataset_long_rele(os->os_dsl_dataset, FTAG); + dsl_dataset_rele(os->os_dsl_dataset, FTAG); return (error); } if (dmu_objset_type(os) != DMU_OST_ZFS) {