diff options
author | mm <mm@FreeBSD.org> | 2013-03-17 18:33:06 +0000 |
---|---|---|
committer | mm <mm@FreeBSD.org> | 2013-03-17 18:33:06 +0000 |
commit | 3d2567990a126eeb3af2fca1367c9749e6bb945f (patch) | |
tree | d0d2bbfdbc121f06d64a6c902181b6dbbca35dc4 /cddl/contrib/opensolaris/lib/libzfs_core | |
parent | 4e6fd9f85c16fb556fb77626827afcaac9104ac7 (diff) | |
download | FreeBSD-src-3d2567990a126eeb3af2fca1367c9749e6bb945f.zip FreeBSD-src-3d2567990a126eeb3af2fca1367c9749e6bb945f.tar.gz |
Add forwards compatibility for libzfs_core
Unsupported: creation of multiple snapshots including "zfs snapshot -r"
Diffstat (limited to 'cddl/contrib/opensolaris/lib/libzfs_core')
4 files changed, 216 insertions, 1 deletions
diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c index b6c28be..c8b401e 100644 --- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c @@ -86,6 +86,10 @@ #include <sys/zfs_ioctl.h> #include <libzfs_compat.h> +#ifdef __FreeBSD__ +extern int zfs_ioctl_version; +#endif + static int g_fd; static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER; static int g_refcount; @@ -124,12 +128,24 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name, zfs_cmd_t zc = { 0 }; int error = 0; char *packed; +#ifdef __FreeBSD__ + nvlist_t *oldsource; +#endif size_t size; ASSERT3S(g_refcount, >, 0); (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); +#ifdef __FreeBSD__ + if (zfs_ioctl_version < ZFS_IOCVER_LZC) { + oldsource = source; + error = lzc_compat_pre(&zc, &ioc, &source); + if (error) + return (error); + } +#endif + packed = fnvlist_pack(source, &size); zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed; zc.zc_nvlist_src_size = size; @@ -167,14 +183,29 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name, break; } } + +#ifdef __FreeBSD__ + if (zfs_ioctl_version < ZFS_IOCVER_LZC) + lzc_compat_post(&zc, ioc); +#endif if (zc.zc_nvlist_dst_filled) { *resultp = fnvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst, zc.zc_nvlist_dst_size); } else if (resultp != NULL) { *resultp = NULL; } - +#ifdef __FreeBSD__ + if (zfs_ioctl_version < ZFS_IOCVER_LZC) + lzc_compat_outnvl(&zc, ioc, resultp); +#endif out: +#ifdef __FreeBSD__ + if (zfs_ioctl_version < ZFS_IOCVER_LZC) { + if (source != oldsource) + nvlist_free(source); + source = oldsource; + } +#endif fnvlist_pack_free(packed, size); free((void *)(uintptr_t)zc.zc_nvlist_dst); return (error); diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h index c8bfbef..ee19d17 100644 --- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h @@ -31,6 +31,9 @@ #include <sys/param.h> #include <sys/types.h> #include <sys/fs/zfs.h> +#ifdef __FreeBSD__ +#include "libzfs_core_compat.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c new file mode 100644 index 0000000..e5eb7ae --- /dev/null +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c @@ -0,0 +1,134 @@ +/* + * CDDL HEADER START + * + * 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 <sys/zfs_ioctl.h> +#include <libzfs_compat.h> + +extern int zfs_ioctl_version; + +int +lzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source) +{ + nvlist_t *nvl = NULL; + nvpair_t *pair; + char *buf; + zfs_ioc_t vecnum; + uint32_t type32; + int error = 0; + int pos; + + if (zfs_ioctl_version >= ZFS_IOCVER_LZC) + return (0); + + vecnum = *ioc; + + switch (vecnum) { + case ZFS_IOC_CREATE: + type32 = fnvlist_lookup_int32(*source, "type"); + zc->zc_objset_type = (uint64_t)type32; + nvlist_lookup_nvlist(*source, "props", &nvl); + *source = nvl; + break; + case ZFS_IOC_CLONE: + buf = fnvlist_lookup_string(*source, "origin"); + strlcpy(zc->zc_value, buf, MAXPATHLEN); + nvlist_lookup_nvlist(*source, "props", &nvl); + *ioc = ZFS_IOC_CREATE; + *source = nvl; + break; + case ZFS_IOC_SNAPSHOT: + nvl = fnvlist_lookup_nvlist(*source, "snaps"); + pair = nvlist_next_nvpair(nvl, NULL); + if (pair != NULL) { + buf = nvpair_name(pair); + pos = strcspn(buf, "@"); + strlcpy(zc->zc_name, buf, pos + 1); + strlcpy(zc->zc_value, buf + pos + 1, MAXPATHLEN); + } else + error = EOPNOTSUPP; + /* old kernel cannot create multiple snapshots */ + if (!error && nvlist_next_nvpair(nvl, pair) != NULL) + error = EOPNOTSUPP; + nvlist_free(nvl); + nvl = NULL; + nvlist_lookup_nvlist(*source, "props", &nvl); + *source = nvl; + break; + case ZFS_IOC_SPACE_SNAPS: + buf = fnvlist_lookup_string(*source, "firstsnap"); + strlcpy(zc->zc_value, buf, MAXPATHLEN); + break; + case ZFS_IOC_DESTROY_SNAPS: + nvl = fnvlist_lookup_nvlist(*source, "snaps"); + pair = nvlist_next_nvpair(nvl, NULL); + if (pair != NULL) { + buf = nvpair_name(pair); + pos = strcspn(buf, "@"); + strlcpy(zc->zc_name, buf, pos + 1); + } + *source = nvl; + break; + } + + return (error); +} + +void +lzc_compat_post(zfs_cmd_t *zc, const zfs_ioc_t ioc) +{ + if (zfs_ioctl_version >= ZFS_IOCVER_LZC) + return; + + switch (ioc) { + case ZFS_IOC_CREATE: + case ZFS_IOC_CLONE: + case ZFS_IOC_SNAPSHOT: + case ZFS_IOC_SPACE_SNAPS: + case ZFS_IOC_DESTROY_SNAPS: + zc->zc_nvlist_dst_filled = B_FALSE; + break; + } +} + +int +lzc_compat_outnvl(zfs_cmd_t *zc, const zfs_ioc_t ioc, nvlist_t **outnvl) +{ + nvlist_t *nvl; + + if (zfs_ioctl_version >= ZFS_IOCVER_LZC) + return (0); + + switch (ioc) { + case ZFS_IOC_SPACE_SNAPS: + nvl = fnvlist_alloc(); + fnvlist_add_uint64(nvl, "used", zc->zc_cookie); + fnvlist_add_uint64(nvl, "compressed", zc->zc_objset_type); + fnvlist_add_uint64(nvl, "uncompressed", zc->zc_perm_action); + *outnvl = nvl; + break; + } + + return (0); +} diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.h b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.h new file mode 100644 index 0000000..6527c4b --- /dev/null +++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.h @@ -0,0 +1,47 @@ +/* + * CDDL HEADER START + * + * 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 by Martin Matuska <mm@FreeBSD.org>. All rights reserved. + */ + +#ifndef _LIBZFS_CORE_COMPAT_H +#define _LIBZFS_CORE_COMPAT_H + +#include <libnvpair.h> +#include <sys/param.h> +#include <sys/types.h> +#include <sys/fs/zfs.h> +#include <sys/zfs_ioctl.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int lzc_compat_pre(zfs_cmd_t *, zfs_ioc_t *, nvlist_t **); +void lzc_compat_post(zfs_cmd_t *, const zfs_ioc_t); +int lzc_compat_outnvl(zfs_cmd_t *, const zfs_ioc_t, nvlist_t **); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBZFS_CORE_COMPAT_H */ |