diff options
Diffstat (limited to 'lib/libzutil')
-rw-r--r-- | lib/libzutil/Makefile.am | 6 | ||||
-rw-r--r-- | lib/libzutil/os/freebsd/zutil_compat.c | 66 |
2 files changed, 64 insertions, 8 deletions
diff --git a/lib/libzutil/Makefile.am b/lib/libzutil/Makefile.am index bbd69b780..cd03ba19d 100644 --- a/lib/libzutil/Makefile.am +++ b/lib/libzutil/Makefile.am @@ -23,10 +23,16 @@ USER_C += \ endif if BUILD_FREEBSD +DEFAULT_INCLUDES += -I$(top_srcdir)/include/os/freebsd/zfs + USER_C += \ os/freebsd/zutil_device_path_os.c \ os/freebsd/zutil_import_os.c \ os/freebsd/zutil_compat.c + +VPATH += $(top_srcdir)/module/os/freebsd/zfs + +nodist_libzutil_la_SOURCES = zfs_ioctl_compat.c endif libzutil_la_SOURCES = $(USER_C) 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); |