Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 1 Mar 2013 09:42:59 +0000 (UTC)
From:      Martin Matuska <mm@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r247540 - in head: cddl/contrib/opensolaris/lib/libzfs/common sys/cddl/contrib/opensolaris/common/zfs sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201303010942.r219gxH0082811@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mm
Date: Fri Mar  1 09:42:58 2013
New Revision: 247540
URL: http://svnweb.freebsd.org/changeset/base/247540

Log:
  Fix the zfs_ioctl compat layer to support zfs_cmd size change introduced
  in r247265 (ZFS deadman thread). Both new utilities now support the old
  kernel and new kernel properly detects old utilities.
  
  For future backwards compatibility, the vfs.zfs.version.ioctl read-only
  sysctl has been introduced. With this sysctl zfs utilities will be able
  to detect the ioctl interface version of the currently loaded zfs module.
  
  As a side effect, the zfs utilities between r247265 and this revision don't
  support the old kernel module. If you are using HEAD newer or equal than
  r247265, install the new kernel module (or whole kernel) first.
  
  MFC after:	10 days

Modified:
  head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
  head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
  head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c

Modified: head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h	Fri Mar  1 09:40:02 2013	(r247539)
+++ head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h	Fri Mar  1 09:42:58 2013	(r247540)
@@ -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_hand
 
 #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);

Modified: head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c	Fri Mar  1 09:40:02 2013	(r247539)
+++ head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c	Fri Mar  1 09:42:58 2013	(r247540)
@@ -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_
 		    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
 }
 
 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
 	    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 
 	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 
 	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);

Modified: head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h	Fri Mar  1 09:40:02 2013	(r247539)
+++ head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h	Fri Mar  1 09:42:58 2013	(r247540)
@@ -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 */

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Fri Mar  1 09:40:02 2013	(r247539)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Fri Mar  1 09:42:58 2013	(r247540)
@@ -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 cm
 	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 cm
 			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);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201303010942.r219gxH0082811>