summaryrefslogtreecommitdiffstats
path: root/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
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/zfs/zfs_ioctl_compat.c
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/zfs/zfs_ioctl_compat.c')
-rw-r--r--sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c207
1 files changed, 181 insertions, 26 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);
OpenPOWER on IntegriCloud