Move common zfs ioctl compatibility functions (userland) into libzfs_compat.c
Introduce additional constants for zfs ioctl versions
This commit is contained in:
parent
d97b41582d
commit
6f4accc2de
103
cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c
Normal file
103
cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* CDDL HEADER SART
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "libzfs_compat.h"
|
||||
|
||||
int zfs_ioctl_version = ZFS_IOCVER_UNDEF;
|
||||
static int zfs_spa_version = -1;
|
||||
|
||||
/*
|
||||
* Get zfs_ioctl_version
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the SPA version
|
||||
*/
|
||||
static int
|
||||
get_zfs_spa_version(void)
|
||||
{
|
||||
size_t ver_size;
|
||||
int ver = 0;
|
||||
|
||||
ver_size = sizeof(ver);
|
||||
sysctlbyname("vfs.zfs.version.spa", &ver, &ver_size, NULL, 0);
|
||||
|
||||
return (ver);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is FreeBSD version of ioctl, because Solaris' ioctl() updates
|
||||
* zc_nvlist_dst_size even if an error is returned, on FreeBSD if an
|
||||
* error is returned zc_nvlist_dst_size won't be updated.
|
||||
*/
|
||||
int
|
||||
zcmd_ioctl(int fd, int 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();
|
||||
|
||||
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
|
||||
*/
|
||||
if (zfs_ioctl_version < ZFS_IOCVER_DEADMAN) {
|
||||
cflag = ZFS_CMD_COMPAT_V28;
|
||||
|
||||
if (zfs_spa_version < 0)
|
||||
zfs_spa_version = get_zfs_spa_version();
|
||||
|
||||
if (zfs_spa_version == SPA_VERSION_15 ||
|
||||
zfs_spa_version == SPA_VERSION_14 ||
|
||||
zfs_spa_version == SPA_VERSION_13)
|
||||
cflag = ZFS_CMD_COMPAT_V15;
|
||||
}
|
||||
|
||||
oldsize = zc->zc_nvlist_dst_size;
|
||||
ret = zcmd_ioctl_compat(fd, request, zc, cflag);
|
||||
|
||||
if (ret == 0 && oldsize < zc->zc_nvlist_dst_size) {
|
||||
ret = -1;
|
||||
errno = ENOMEM;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
@ -32,71 +32,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static int zfs_ioctl_version = -1;
|
||||
static int zfs_kernel_version = 0;
|
||||
int get_zfs_ioctl_version(void);
|
||||
int zcmd_ioctl(int fd, int request, zfs_cmd_t *zc);
|
||||
|
||||
/*
|
||||
* Get zfs_ioctl_version
|
||||
*/
|
||||
static __inline int
|
||||
get_zfs_ioctl_version(void)
|
||||
{
|
||||
size_t ver_size;
|
||||
int ver = 0;
|
||||
|
||||
ver_size = sizeof(ver);
|
||||
sysctlbyname("vfs.zfs.version.ioctl", &ver, &ver_size, NULL, 0);
|
||||
|
||||
return (ver);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is FreeBSD version of ioctl, because Solaris' ioctl() updates
|
||||
* zc_nvlist_dst_size even if an error is returned, on FreeBSD if an
|
||||
* error is returned zc_nvlist_dst_size won't be updated.
|
||||
*/
|
||||
static __inline int
|
||||
zcmd_ioctl(int fd, int request, zfs_cmd_t *zc)
|
||||
{
|
||||
size_t oldsize, zfs_kernel_version_size;
|
||||
int version, ret, cflag = ZFS_CMD_COMPAT_NONE;
|
||||
|
||||
if (zfs_ioctl_version == -1)
|
||||
zfs_ioctl_version = get_zfs_ioctl_version();
|
||||
|
||||
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
|
||||
*/
|
||||
if (zfs_ioctl_version < ZFS_IOCVER_DEADMAN) {
|
||||
cflag = ZFS_CMD_COMPAT_V28;
|
||||
zfs_kernel_version_size = sizeof(zfs_kernel_version);
|
||||
|
||||
if (zfs_kernel_version == 0) {
|
||||
sysctlbyname("vfs.zfs.version.spa",
|
||||
&zfs_kernel_version,
|
||||
&zfs_kernel_version_size, NULL, 0);
|
||||
}
|
||||
|
||||
if (zfs_kernel_version == SPA_VERSION_15 ||
|
||||
zfs_kernel_version == SPA_VERSION_14 ||
|
||||
zfs_kernel_version == SPA_VERSION_13)
|
||||
cflag = ZFS_CMD_COMPAT_V15;
|
||||
}
|
||||
|
||||
oldsize = zc->zc_nvlist_dst_size;
|
||||
ret = zcmd_ioctl_compat(fd, request, zc, cflag);
|
||||
|
||||
if (ret == 0 && oldsize < zc->zc_nvlist_dst_size) {
|
||||
ret = -1;
|
||||
errno = ENOMEM;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
#define ioctl(fd, ioc, zc) zcmd_ioctl((fd), (ioc), (zc))
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -88,7 +88,7 @@
|
||||
#include "libzfs_compat.h"
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
int lzc_ioctl_version = -1;
|
||||
extern int zfs_ioctl_version;
|
||||
#endif
|
||||
|
||||
static int g_fd;
|
||||
@ -140,10 +140,10 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
|
||||
(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (lzc_ioctl_version == -1)
|
||||
lzc_ioctl_version = get_zfs_ioctl_version();
|
||||
if (zfs_ioctl_version == ZFS_IOCVER_UNDEF)
|
||||
zfs_ioctl_version = get_zfs_ioctl_version();
|
||||
|
||||
if (lzc_ioctl_version < ZFS_IOCVER_LZC) {
|
||||
if (zfs_ioctl_version < ZFS_IOCVER_LZC) {
|
||||
oldsource = source;
|
||||
error = lzc_compat_pre(&zc, &ioc, &source);
|
||||
if (error)
|
||||
@ -190,7 +190,7 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (lzc_ioctl_version < ZFS_IOCVER_LZC)
|
||||
if (zfs_ioctl_version < ZFS_IOCVER_LZC)
|
||||
lzc_compat_post(&zc, ioc);
|
||||
#endif
|
||||
if (zc.zc_nvlist_dst_filled) {
|
||||
@ -200,12 +200,12 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
|
||||
*resultp = NULL;
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
if (lzc_ioctl_version < ZFS_IOCVER_LZC)
|
||||
if (zfs_ioctl_version < ZFS_IOCVER_LZC)
|
||||
lzc_compat_outnvl(&zc, ioc, resultp);
|
||||
#endif
|
||||
out:
|
||||
#ifdef __FreeBSD__
|
||||
if (lzc_ioctl_version < ZFS_IOCVER_LZC) {
|
||||
if (zfs_ioctl_version < ZFS_IOCVER_LZC) {
|
||||
if (source != oldsource)
|
||||
nvlist_free(source);
|
||||
source = oldsource;
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <zfs_ioctl_compat.h>
|
||||
#include "libzfs_core_compat.h"
|
||||
|
||||
extern int lzc_ioctl_version;
|
||||
extern int zfs_ioctl_version;
|
||||
|
||||
int
|
||||
lzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source)
|
||||
@ -40,7 +40,7 @@ lzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source)
|
||||
int error = 0;
|
||||
int pos;
|
||||
|
||||
if (lzc_ioctl_version >= ZFS_IOCVER_LZC)
|
||||
if (zfs_ioctl_version >= ZFS_IOCVER_LZC)
|
||||
return (0);
|
||||
|
||||
vecnum = *ioc;
|
||||
@ -99,7 +99,7 @@ lzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source)
|
||||
void
|
||||
lzc_compat_post(zfs_cmd_t *zc, const zfs_ioc_t ioc)
|
||||
{
|
||||
if (lzc_ioctl_version >= ZFS_IOCVER_LZC)
|
||||
if (zfs_ioctl_version >= ZFS_IOCVER_LZC)
|
||||
return;
|
||||
|
||||
switch (ioc) {
|
||||
@ -118,7 +118,7 @@ lzc_compat_outnvl(zfs_cmd_t *zc, const zfs_ioc_t ioc, nvlist_t **outnvl)
|
||||
{
|
||||
nvlist_t *nvl;
|
||||
|
||||
if (lzc_ioctl_version >= ZFS_IOCVER_LZC)
|
||||
if (zfs_ioctl_version >= ZFS_IOCVER_LZC)
|
||||
return (0);
|
||||
|
||||
switch (ioc) {
|
||||
|
@ -18,6 +18,7 @@ SRCS= deviceid.c \
|
||||
zone.c
|
||||
|
||||
SRCS+= libzfs_changelist.c \
|
||||
libzfs_compat.c \
|
||||
libzfs_config.c \
|
||||
libzfs_dataset.c \
|
||||
libzfs_diff.c \
|
||||
|
@ -4,12 +4,16 @@
|
||||
.PATH: ${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/zfs
|
||||
.PATH: ${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/fs/zfs
|
||||
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs_core/common
|
||||
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs/common
|
||||
|
||||
LIB= zfs_core
|
||||
DPADD= ${LIBNVPAIR}
|
||||
LDADD= -lnvpair
|
||||
|
||||
SRCS= libzfs_core.c libzfs_core_compat.c
|
||||
SRCS= libzfs_core.c \
|
||||
libzfs_core_compat.c
|
||||
|
||||
SRCS+= libzfs_compat.c
|
||||
|
||||
WARNS?= 0
|
||||
CSTD= c99
|
||||
|
@ -45,8 +45,10 @@ extern "C" {
|
||||
*/
|
||||
|
||||
/* ioctl versions for vfs.zfs.version.ioctl */
|
||||
#define ZFS_IOCVER_LZC 2
|
||||
#define ZFS_IOCVER_UNDEF -1
|
||||
#define ZFS_IOCVER_NONE 0
|
||||
#define ZFS_IOCVER_DEADMAN 1
|
||||
#define ZFS_IOCVER_LZC 2
|
||||
#define ZFS_IOCVER_CURRENT ZFS_IOCVER_LZC
|
||||
|
||||
/* compatibility conversion flag */
|
||||
|
Loading…
x
Reference in New Issue
Block a user