summaryrefslogtreecommitdiffstats
path: root/sys/cddl/contrib/opensolaris/common
diff options
context:
space:
mode:
authormm <mm@FreeBSD.org>2013-03-01 09:42:58 +0000
committermm <mm@FreeBSD.org>2013-03-01 09:42:58 +0000
commite653c470f763b4dff0b51050c92e379b1ff3f646 (patch)
tree6a0f6613d26f6954346147f7c33ceb0283ec85d9 /sys/cddl/contrib/opensolaris/common
parent9ecef62d739ff26f081c6ce4d79c74c293ba9fee (diff)
downloadFreeBSD-src-e653c470f763b4dff0b51050c92e379b1ff3f646.zip
FreeBSD-src-e653c470f763b4dff0b51050c92e379b1ff3f646.tar.gz
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
Diffstat (limited to 'sys/cddl/contrib/opensolaris/common')
-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
2 files changed, 249 insertions, 30 deletions
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 */
OpenPOWER on IntegriCloud