Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 17 Mar 2013 10:57:05 +0000 (UTC)
From:      Martin Matuska <mm@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r248421 - in projects/libzfs_core: cddl/contrib/opensolaris/lib/libzfs/common sys/cddl/contrib/opensolaris/common/zfs sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201303171057.r2HAv5Kr059691@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mm
Date: Sun Mar 17 10:57:04 2013
New Revision: 248421
URL: http://svnweb.freebsd.org/changeset/base/248421

Log:
  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

Modified:
  projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h
  projects/libzfs_core/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
  projects/libzfs_core/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h
  projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c

Modified: projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h
==============================================================================
--- projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h	Sun Mar 17 07:49:44 2013	(r248420)
+++ projects/libzfs_core/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.h	Sun Mar 17 10:57:04 2013	(r248421)
@@ -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_
 	}
 
 	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_
 
 	return (ret);
 }
-#define	ioctl(fd, cmd, zc)	zcmd_ioctl((fd), (cmd), (zc))
+#define	ioctl(fd, ioc, zc)	zcmd_ioctl((fd), (ioc), (zc))
 
 #ifdef	__cplusplus
 }

Modified: projects/libzfs_core/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
==============================================================================
--- projects/libzfs_core/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c	Sun Mar 17 07:49:44 2013	(r248420)
+++ projects/libzfs_core/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c	Sun Mar 17 10:57:04 2013	(r248421)
@@ -33,6 +33,7 @@
 #include <sys/nvpair.h>
 #include <sys/dsl_deleg.h>
 #include <sys/zfs_ioctl.h>
+#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_
 {
 	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_
 {
 	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_
 
 #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 
 
 	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 
 	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 
 	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
 {
 	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
 		}
 	}
 }
+
+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 */

Modified: projects/libzfs_core/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h
==============================================================================
--- projects/libzfs_core/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h	Sun Mar 17 07:49:44 2013	(r248420)
+++ projects/libzfs_core/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h	Sun Mar 17 10:57:04 2013	(r248421)
@@ -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_v1
 #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);

Modified: projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
==============================================================================
--- projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Sun Mar 17 07:49:44 2013	(r248420)
+++ projects/libzfs_core/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Sun Mar 17 10:57:04 2013	(r248421)
@@ -5805,7 +5805,7 @@ zfsdev_ioctl(struct cdev *dev, u_long zc
 #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 zc
 	 * 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 zc
 		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 zc
 			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 zc
 		}
 		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) {



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