aboutsummaryrefslogtreecommitdiffstats
path: root/lib/libzutil/os
diff options
context:
space:
mode:
authorMatthew Macy <[email protected]>2020-07-15 21:32:50 -0700
committerGitHub <[email protected]>2020-07-15 21:32:50 -0700
commit23c871671c7bc2c79ad6ec1804715f405058cdb6 (patch)
tree62f69f26a34174de4de3d12d3941fe480cc1c2ce /lib/libzutil/os
parentf1b815379422b840b01bbb25f40140d774f84692 (diff)
FreeBSD: zfs commands backward compatibility
Update the zfs commands such that they're backwards compatible with the version of ZFS is the base FreeBSD. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Signed-off-by: Matt Macy <[email protected]> Closes #10542
Diffstat (limited to 'lib/libzutil/os')
-rw-r--r--lib/libzutil/os/freebsd/zutil_compat.c66
1 files changed, 58 insertions, 8 deletions
diff --git a/lib/libzutil/os/freebsd/zutil_compat.c b/lib/libzutil/os/freebsd/zutil_compat.c
index 5b0fe8548..3e70fef1e 100644
--- a/lib/libzutil/os/freebsd/zutil_compat.c
+++ b/lib/libzutil/os/freebsd/zutil_compat.c
@@ -20,15 +20,35 @@
*/
#include <sys/types.h>
#include <sys/param.h>
+#include <sys/sysctl.h>
#include <sys/zfs_ioctl.h>
#include <os/freebsd/zfs/sys/zfs_ioctl_compat.h>
#include <libzutil.h>
+#include <err.h>
+
+int zfs_ioctl_version = ZFS_IOCVER_UNDEF;
+
+/*
+ * Get zfs_ioctl_version
+ */
+static int
+get_zfs_ioctl_version(void)
+{
+ size_t ver_size;
+ int ver = ZFS_IOCVER_NONE;
+
+ ver_size = sizeof (ver);
+ sysctlbyname("vfs.zfs.version.ioctl", &ver, &ver_size, NULL, 0);
+
+ return (ver);
+}
+
static int
zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag)
{
- int ret;
- void *zc_c;
+ int newrequest, ret;
+ void *zc_c = NULL;
unsigned long ncmd;
zfs_iocparm_t zp;
@@ -37,17 +57,32 @@ zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag)
ncmd = _IOWR('Z', request, zfs_iocparm_t);
zp.zfs_cmd = (uint64_t)zc;
zp.zfs_cmd_size = sizeof (zfs_cmd_t);
- zp.zfs_ioctl_version = ZFS_IOCVER_ZOF;
- return (ioctl(fd, ncmd, &zp));
+ zp.zfs_ioctl_version = ZFS_IOCVER_OZFS;
+ break;
+ case ZFS_CMD_COMPAT_LEGACY:
+ newrequest = zfs_ioctl_ozfs_to_legacy(request);
+ ncmd = _IOWR('Z', newrequest, zfs_iocparm_t);
+ zc_c = malloc(sizeof (zfs_cmd_legacy_t));
+ zfs_cmd_ozfs_to_legacy(zc, zc_c);
+ zp.zfs_cmd = (uint64_t)zc_c;
+ zp.zfs_cmd_size = sizeof (zfs_cmd_legacy_t);
+ zp.zfs_ioctl_version = ZFS_IOCVER_LEGACY;
+ break;
default:
abort();
return (EINVAL);
}
- ret = ioctl(fd, ncmd, zc_c);
- zfs_cmd_compat_get(zc, (caddr_t)zc_c, cflag);
- free(zc_c);
-
+ ret = ioctl(fd, ncmd, &zp);
+ if (ret) {
+ if (zc_c)
+ free(zc_c);
+ return (ret);
+ }
+ if (zc_c) {
+ zfs_cmd_legacy_to_ozfs(zc_c, zc);
+ free(zc_c);
+ }
return (ret);
}
@@ -62,6 +97,21 @@ zfs_ioctl_fd(int fd, unsigned long request, zfs_cmd_t *zc)
size_t oldsize;
int ret, cflag = ZFS_CMD_COMPAT_NONE;
+ if (zfs_ioctl_version == ZFS_IOCVER_UNDEF)
+ zfs_ioctl_version = get_zfs_ioctl_version();
+
+ switch (zfs_ioctl_version) {
+ case ZFS_IOCVER_LEGACY:
+ cflag = ZFS_CMD_COMPAT_LEGACY;
+ break;
+ case ZFS_IOCVER_OZFS:
+ cflag = ZFS_CMD_COMPAT_NONE;
+ break;
+ default:
+ errx(1, "unrecognized zfs ioctl version %d",
+ zfs_ioctl_version);
+ }
+
oldsize = zc->zc_nvlist_dst_size;
ret = zcmd_ioctl_compat(fd, request, zc, cflag);