summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h35
-rw-r--r--sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c207
-rw-r--r--sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h72
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c17
4 files changed, 287 insertions, 44 deletions
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
index 1c46d32..be07187 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
@@ -24,6 +24,7 @@
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
*/
#ifndef _LIBFS_IMPL_H
@@ -216,6 +217,7 @@ 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
@@ -225,19 +227,34 @@ static int zfs_kernel_version = 0;
static __inline int
zcmd_ioctl(int fd, unsigned long cmd, zfs_cmd_t *zc)
{
- size_t oldsize, zfs_kernel_version_size;
+ size_t oldsize, zfs_kernel_version_size, zfs_ioctl_version_size;
int version, ret, cflag = ZFS_CMD_COMPAT_NONE;
- 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);
+ 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_kernel_version == SPA_VERSION_15 ||
- zfs_kernel_version == SPA_VERSION_14 ||
- zfs_kernel_version == SPA_VERSION_13)
- cflag = ZFS_CMD_COMPAT_V15;
+ /*
+ * 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);
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 0b43c78..4959335 100644
--- a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
+++ b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
+ * Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Portions Copyright 2005, 2010, Oracle and/or its affiliates.
* All rights reserved.
* Use is subject to license terms.
@@ -35,22 +35,100 @@
#include <sys/zfs_ioctl.h>
#include "zfs_ioctl_compat.h"
+static int zfs_version_ioctl = ZFS_IOCVER_CURRENT;
+SYSCTL_DECL(_vfs_zfs_version);
+SYSCTL_INT(_vfs_zfs_version, OID_AUTO, ioctl, CTLFLAG_RD, &zfs_version_ioctl,
+ 0, "ZFS_IOCTL_VERSION");
+
/*
- * FreeBSD zfs_cmd compatibility with v15 and older binaries
+ * FreeBSD zfs_cmd compatibility with older binaries
* appropriately remap/extend the zfs_cmd_t structure
*/
void
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;
- if (cflag == ZFS_CMD_COMPAT_V15) {
+ switch (cflag) {
+ case ZFS_CMD_COMPAT_V28:
+ zc28_c = (void *)addr;
+
+ /* zc */
+ strlcpy(zc->zc_name, zc28_c->zc_name, MAXPATHLEN);
+ strlcpy(zc->zc_value, zc28_c->zc_value, MAXPATHLEN * 2);
+ strlcpy(zc->zc_string, zc28_c->zc_string, MAXPATHLEN);
+ strlcpy(zc->zc_top_ds, zc28_c->zc_top_ds, MAXPATHLEN);
+ zc->zc_guid = zc28_c->zc_guid;
+ zc->zc_nvlist_conf = zc28_c->zc_nvlist_conf;
+ zc->zc_nvlist_conf_size = zc28_c->zc_nvlist_conf_size;
+ zc->zc_nvlist_src = zc28_c->zc_nvlist_src;
+ zc->zc_nvlist_src_size = zc28_c->zc_nvlist_src_size;
+ zc->zc_nvlist_dst = zc28_c->zc_nvlist_dst;
+ zc->zc_nvlist_dst_size = zc28_c->zc_nvlist_dst_size;
+ zc->zc_cookie = zc28_c->zc_cookie;
+ zc->zc_objset_type = zc28_c->zc_objset_type;
+ zc->zc_perm_action = zc28_c->zc_perm_action;
+ zc->zc_history = zc28_c->zc_history;
+ zc->zc_history_len = zc28_c->zc_history_len;
+ zc->zc_history_offset = zc28_c->zc_history_offset;
+ zc->zc_obj = zc28_c->zc_obj;
+ zc->zc_iflags = zc28_c->zc_iflags;
+ zc->zc_share = zc28_c->zc_share;
+ zc->zc_jailid = zc28_c->zc_jailid;
+ zc->zc_objset_stats = zc28_c->zc_objset_stats;
+ zc->zc_begin_record = zc28_c->zc_begin_record;
+ zc->zc_defer_destroy = zc28_c->zc_defer_destroy;
+ zc->zc_temphold = zc28_c->zc_temphold;
+ zc->zc_action_handle = zc28_c->zc_action_handle;
+ zc->zc_cleanup_fd = zc28_c->zc_cleanup_fd;
+ zc->zc_simple = zc28_c->zc_simple;
+ bcopy(zc28_c->zc_pad, zc->zc_pad, sizeof(zc->zc_pad));
+ zc->zc_sendobj = zc28_c->zc_sendobj;
+ zc->zc_fromobj = zc28_c->zc_fromobj;
+ zc->zc_createtxg = zc28_c->zc_createtxg;
+ zc->zc_stat = zc28_c->zc_stat;
+
+ /* zc->zc_inject_record */
+ zc->zc_inject_record.zi_objset =
+ zc28_c->zc_inject_record.zi_objset;
+ zc->zc_inject_record.zi_object =
+ zc28_c->zc_inject_record.zi_object;
+ zc->zc_inject_record.zi_start =
+ zc28_c->zc_inject_record.zi_start;
+ zc->zc_inject_record.zi_end =
+ zc28_c->zc_inject_record.zi_end;
+ zc->zc_inject_record.zi_guid =
+ zc28_c->zc_inject_record.zi_guid;
+ zc->zc_inject_record.zi_level =
+ zc28_c->zc_inject_record.zi_level;
+ zc->zc_inject_record.zi_error =
+ zc28_c->zc_inject_record.zi_error;
+ zc->zc_inject_record.zi_type =
+ zc28_c->zc_inject_record.zi_type;
+ zc->zc_inject_record.zi_freq =
+ zc28_c->zc_inject_record.zi_freq;
+ zc->zc_inject_record.zi_failfast =
+ zc28_c->zc_inject_record.zi_failfast;
+ strlcpy(zc->zc_inject_record.zi_func,
+ zc28_c->zc_inject_record.zi_func, MAXNAMELEN);
+ zc->zc_inject_record.zi_iotype =
+ zc28_c->zc_inject_record.zi_iotype;
+ zc->zc_inject_record.zi_duration =
+ zc28_c->zc_inject_record.zi_duration;
+ zc->zc_inject_record.zi_timer =
+ zc28_c->zc_inject_record.zi_timer;
+ zc->zc_inject_record.zi_cmd = ZINJECT_UNINITIALIZED;
+ zc->zc_inject_record.zi_pad = 0;
+ break;
+
+ case ZFS_CMD_COMPAT_V15:
zc_c = (void *)addr;
/* zc */
- strlcpy(zc->zc_name,zc_c->zc_name,MAXPATHLEN);
- strlcpy(zc->zc_value,zc_c->zc_value,MAXPATHLEN);
- strlcpy(zc->zc_string,zc_c->zc_string,MAXPATHLEN);
+ strlcpy(zc->zc_name, zc_c->zc_name, MAXPATHLEN);
+ strlcpy(zc->zc_value, zc_c->zc_value, MAXPATHLEN);
+ strlcpy(zc->zc_string, zc_c->zc_string, MAXPATHLEN);
zc->zc_guid = zc_c->zc_guid;
zc->zc_nvlist_conf = zc_c->zc_nvlist_conf;
zc->zc_nvlist_conf_size = zc_c->zc_nvlist_conf_size;
@@ -91,6 +169,7 @@ zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_t addr, const int cflag)
zc_c->zc_inject_record.zi_freq;
zc->zc_inject_record.zi_failfast =
zc_c->zc_inject_record.zi_failfast;
+ break;
}
}
@@ -98,15 +177,84 @@ void
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;
switch (cflag) {
+ case ZFS_CMD_COMPAT_V28:
+ zc28_c = (void *)addr;
+
+ strlcpy(zc28_c->zc_name, zc->zc_name, MAXPATHLEN);
+ strlcpy(zc28_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
+ strlcpy(zc28_c->zc_string, zc->zc_string, MAXPATHLEN);
+ strlcpy(zc28_c->zc_top_ds, zc->zc_top_ds, MAXPATHLEN);
+ zc28_c->zc_guid = zc->zc_guid;
+ zc28_c->zc_nvlist_conf = zc->zc_nvlist_conf;
+ zc28_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
+ zc28_c->zc_nvlist_src = zc->zc_nvlist_src;
+ zc28_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
+ zc28_c->zc_nvlist_dst = zc->zc_nvlist_dst;
+ zc28_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
+ zc28_c->zc_cookie = zc->zc_cookie;
+ zc28_c->zc_objset_type = zc->zc_objset_type;
+ zc28_c->zc_perm_action = zc->zc_perm_action;
+ zc28_c->zc_history = zc->zc_history;
+ zc28_c->zc_history_len = zc->zc_history_len;
+ zc28_c->zc_history_offset = zc->zc_history_offset;
+ zc28_c->zc_obj = zc->zc_obj;
+ zc28_c->zc_iflags = zc->zc_iflags;
+ zc28_c->zc_share = zc->zc_share;
+ zc28_c->zc_jailid = zc->zc_jailid;
+ zc28_c->zc_objset_stats = zc->zc_objset_stats;
+ zc28_c->zc_begin_record = zc->zc_begin_record;
+ zc28_c->zc_defer_destroy = zc->zc_defer_destroy;
+ zc28_c->zc_temphold = zc->zc_temphold;
+ zc28_c->zc_action_handle = zc->zc_action_handle;
+ zc28_c->zc_cleanup_fd = zc->zc_cleanup_fd;
+ zc28_c->zc_simple = zc->zc_simple;
+ bcopy(zc->zc_pad, zc28_c->zc_pad, sizeof(zc28_c->zc_pad));
+ zc28_c->zc_sendobj = zc->zc_sendobj;
+ zc28_c->zc_fromobj = zc->zc_fromobj;
+ zc28_c->zc_createtxg = zc->zc_createtxg;
+ zc28_c->zc_stat = zc->zc_stat;
+
+ /* zc_inject_record */
+ zc28_c->zc_inject_record.zi_objset =
+ zc->zc_inject_record.zi_objset;
+ zc28_c->zc_inject_record.zi_object =
+ zc->zc_inject_record.zi_object;
+ zc28_c->zc_inject_record.zi_start =
+ zc->zc_inject_record.zi_start;
+ zc28_c->zc_inject_record.zi_end =
+ zc->zc_inject_record.zi_end;
+ zc28_c->zc_inject_record.zi_guid =
+ zc->zc_inject_record.zi_guid;
+ zc28_c->zc_inject_record.zi_level =
+ zc->zc_inject_record.zi_level;
+ zc28_c->zc_inject_record.zi_error =
+ zc->zc_inject_record.zi_error;
+ zc28_c->zc_inject_record.zi_type =
+ zc->zc_inject_record.zi_type;
+ zc28_c->zc_inject_record.zi_freq =
+ zc->zc_inject_record.zi_freq;
+ zc28_c->zc_inject_record.zi_failfast =
+ zc->zc_inject_record.zi_failfast;
+ strlcpy(zc28_c->zc_inject_record.zi_func,
+ zc->zc_inject_record.zi_func, MAXNAMELEN);
+ zc28_c->zc_inject_record.zi_iotype =
+ zc->zc_inject_record.zi_iotype;
+ zc28_c->zc_inject_record.zi_duration =
+ zc->zc_inject_record.zi_duration;
+ zc28_c->zc_inject_record.zi_timer =
+ zc->zc_inject_record.zi_timer;
+ break;
+
case ZFS_CMD_COMPAT_V15:
zc_c = (void *)addr;
/* zc */
- strlcpy(zc_c->zc_name,zc->zc_name,MAXPATHLEN);
- strlcpy(zc_c->zc_value,zc->zc_value,MAXPATHLEN);
- strlcpy(zc_c->zc_string,zc->zc_string,MAXPATHLEN);
+ strlcpy(zc_c->zc_name, zc->zc_name, MAXPATHLEN);
+ strlcpy(zc_c->zc_value, zc->zc_value, MAXPATHLEN);
+ strlcpy(zc_c->zc_string, zc->zc_string, MAXPATHLEN);
zc_c->zc_guid = zc->zc_guid;
zc_c->zc_nvlist_conf = zc->zc_nvlist_conf;
zc_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
@@ -260,7 +408,7 @@ zfs_ioctl_compat_fix_stats_nvlist(nvlist_t *nvl)
}
static int
-zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int cflag)
+zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int nc)
{
nvlist_t *nv, *nvp = NULL;
nvpair_t *elem;
@@ -270,7 +418,7 @@ zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int cflag)
zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
return (error);
- if (cflag == 5) { /* ZFS_IOC_POOL_STATS */
+ if (nc == 5) { /* ZFS_IOC_POOL_STATS */
elem = NULL;
while ((elem = nvlist_next_nvpair(nv, elem)) != NULL) {
if (nvpair_value_nvlist(elem, &nvp) == 0)
@@ -334,17 +482,22 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag)
void *zc_c;
unsigned long ncmd;
- if (cflag == ZFS_CMD_COMPAT_NONE) {
+ switch (cflag) {
+ case ZFS_CMD_COMPAT_NONE:
ret = ioctl(fd, cmd, zc);
return (ret);
- }
-
- if (cflag == ZFS_CMD_COMPAT_V15) {
+ case ZFS_CMD_COMPAT_V28:
+ zc_c = malloc(sizeof(zfs_cmd_v28_t));
+ ncmd = _IOWR('Z', ZFS_IOC(cmd), struct zfs_cmd_v28);
+ break;
+ case ZFS_CMD_COMPAT_V15:
nc = zfs_ioctl_v28_to_v15[ZFS_IOC(cmd)];
zc_c = malloc(sizeof(zfs_cmd_v15_t));
ncmd = _IOWR('Z', nc, struct zfs_cmd_v15);
- } else
+ break;
+ default:
return (EINVAL);
+ }
if (ZFS_IOC(ncmd) == ZFS_IOC_COMPAT_FAIL)
return (ENOTSUP);
@@ -358,16 +511,18 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag)
zfs_cmd_compat_get(zc, (caddr_t)zc_c, cflag);
free(zc_c);
- 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 */
- zfs_ioctl_compat_fix_stats(zc, nc);
- break;
- case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
- zfs_ioctl_compat_pool_get_props(zc);
- break;
+ 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 */
+ zfs_ioctl_compat_fix_stats(zc, nc);
+ break;
+ case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
+ zfs_ioctl_compat_pool_get_props(zc);
+ break;
+ }
}
return (ret);
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 03d648c..b20ceca 100644
--- a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h
+++ b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
+ * Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Use is subject to license terms.
*/
@@ -40,11 +40,21 @@
extern "C" {
#endif
-#define ZFS_CMD_COMPAT_NONE 0
+/*
+ * Backwards ioctl compatibility
+ */
+
+/* ioctl versions for vfs.zfs.version.ioctl */
+#define ZFS_IOCVER_DEADMAN 1
+#define ZFS_IOCVER_CURRENT ZFS_IOCVER_DEADMAN
+
+/* compatibility conversion flag */
+#define ZFS_CMD_COMPAT_NONE 0
#define ZFS_CMD_COMPAT_V15 1
+#define ZFS_CMD_COMPAT_V28 2
-#define ZFS_IOC_COMPAT_PASS 254
-#define ZFS_IOC_COMPAT_FAIL 255
+#define ZFS_IOC_COMPAT_PASS 254
+#define ZFS_IOC_COMPAT_FAIL 255
typedef struct zinject_record_v15 {
uint64_t zi_objset;
@@ -84,6 +94,60 @@ typedef struct zfs_cmd_v15 {
zinject_record_v15_t zc_inject_record;
} zfs_cmd_v15_t;
+typedef struct zinject_record_v28 {
+ uint64_t zi_objset;
+ uint64_t zi_object;
+ uint64_t zi_start;
+ uint64_t zi_end;
+ uint64_t zi_guid;
+ uint32_t zi_level;
+ uint32_t zi_error;
+ uint64_t zi_type;
+ uint32_t zi_freq;
+ uint32_t zi_failfast;
+ char zi_func[MAXNAMELEN];
+ uint32_t zi_iotype;
+ int32_t zi_duration;
+ uint64_t zi_timer;
+} zinject_record_v28_t;
+
+typedef struct zfs_cmd_v28 {
+ 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;
+ zinject_record_v28_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_v28_t;
+
#ifdef _KERNEL
unsigned static long zfs_ioctl_v15_to_v28[] = {
0, /* 0 ZFS_IOC_POOL_CREATE */
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 9925a3b..af0c9f7 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
@@ -23,7 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
- * Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org>
+ * Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
@@ -5331,12 +5331,14 @@ zfsdev_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
len = IOCPARM_LEN(cmd);
/*
- * Check if we have sufficient kernel memory allocated
- * for the zfs_cmd_t request. Bail out if not so we
- * will not access undefined memory region.
+ * Check if we are talking to supported older binaries
+ * and translate zfs_cmd if necessary
*/
if (len < sizeof(zfs_cmd_t))
- if (len == sizeof(zfs_cmd_v15_t)) {
+ if (len == sizeof(zfs_cmd_v28_t)) {
+ cflag = ZFS_CMD_COMPAT_V28;
+ vec = ZFS_IOC(cmd);
+ } else if (len == sizeof(zfs_cmd_v15_t)) {
cflag = ZFS_CMD_COMPAT_V15;
vec = zfs_ioctl_v15_to_v28[ZFS_IOC(cmd)];
} else
@@ -5351,6 +5353,11 @@ zfsdev_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
return (ENOTSUP);
}
+ /*
+ * Check if we have sufficient kernel memory allocated
+ * for the zfs_cmd_t request. Bail out if not so we
+ * will not access undefined memory region.
+ */
if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0]))
return (EINVAL);
OpenPOWER on IntegriCloud