1248435Smm/* 2248435Smm * CDDL HEADER START 3248435Smm * 4248435Smm * The contents of this file are subject to the terms of the 5248435Smm * Common Development and Distribution License (the "License"). 6248435Smm * You may not use this file except in compliance with the License. 7248435Smm * 8248435Smm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9248435Smm * or http://www.opensolaris.org/os/licensing. 10248435Smm * See the License for the specific language governing permissions 11248435Smm * and limitations under the License. 12248435Smm * 13248435Smm * When distributing Covered Code, include this CDDL HEADER in each 14248435Smm * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15248435Smm * If applicable, add the following below this CDDL HEADER, with the 16248435Smm * fields enclosed by brackets "[]" replaced with your own identifying 17248435Smm * information: Portions Copyright [yyyy] [name of copyright owner] 18248435Smm * 19248435Smm * CDDL HEADER END 20248435Smm */ 21248435Smm 22248435Smm/* 23248435Smm * Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved. 24248435Smm */ 25248435Smm 26248435Smm#include <sys/zfs_ioctl.h> 27248445Smm#include <zfs_ioctl_compat.h> 28248445Smm#include "libzfs_core_compat.h" 29248435Smm 30248461Smmextern int zfs_ioctl_version; 31248435Smm 32248435Smmint 33248435Smmlzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source) 34248435Smm{ 35248435Smm nvlist_t *nvl = NULL; 36248498Smm nvpair_t *pair, *hpair; 37248498Smm char *buf, *val; 38248435Smm zfs_ioc_t vecnum; 39248435Smm uint32_t type32; 40248498Smm int32_t cleanup_fd; 41248435Smm int error = 0; 42248435Smm int pos; 43248435Smm 44248461Smm if (zfs_ioctl_version >= ZFS_IOCVER_LZC) 45248435Smm return (0); 46248435Smm 47248435Smm vecnum = *ioc; 48248435Smm 49248435Smm switch (vecnum) { 50248435Smm case ZFS_IOC_CREATE: 51248435Smm type32 = fnvlist_lookup_int32(*source, "type"); 52248435Smm zc->zc_objset_type = (uint64_t)type32; 53248435Smm nvlist_lookup_nvlist(*source, "props", &nvl); 54248435Smm *source = nvl; 55248435Smm break; 56248435Smm case ZFS_IOC_CLONE: 57248435Smm buf = fnvlist_lookup_string(*source, "origin"); 58248435Smm strlcpy(zc->zc_value, buf, MAXPATHLEN); 59248435Smm nvlist_lookup_nvlist(*source, "props", &nvl); 60248435Smm *ioc = ZFS_IOC_CREATE; 61248435Smm *source = nvl; 62248435Smm break; 63248435Smm case ZFS_IOC_SNAPSHOT: 64248435Smm nvl = fnvlist_lookup_nvlist(*source, "snaps"); 65248435Smm pair = nvlist_next_nvpair(nvl, NULL); 66248435Smm if (pair != NULL) { 67248435Smm buf = nvpair_name(pair); 68248435Smm pos = strcspn(buf, "@"); 69248435Smm strlcpy(zc->zc_name, buf, pos + 1); 70248435Smm strlcpy(zc->zc_value, buf + pos + 1, MAXPATHLEN); 71248435Smm } else 72248498Smm error = EINVAL; 73248435Smm /* old kernel cannot create multiple snapshots */ 74248435Smm if (!error && nvlist_next_nvpair(nvl, pair) != NULL) 75248435Smm error = EOPNOTSUPP; 76248435Smm nvlist_free(nvl); 77248435Smm nvl = NULL; 78248435Smm nvlist_lookup_nvlist(*source, "props", &nvl); 79248435Smm *source = nvl; 80248435Smm break; 81248435Smm case ZFS_IOC_SPACE_SNAPS: 82248435Smm buf = fnvlist_lookup_string(*source, "firstsnap"); 83248435Smm strlcpy(zc->zc_value, buf, MAXPATHLEN); 84248435Smm break; 85248435Smm case ZFS_IOC_DESTROY_SNAPS: 86248435Smm nvl = fnvlist_lookup_nvlist(*source, "snaps"); 87248435Smm pair = nvlist_next_nvpair(nvl, NULL); 88248435Smm if (pair != NULL) { 89248435Smm buf = nvpair_name(pair); 90248435Smm pos = strcspn(buf, "@"); 91248435Smm strlcpy(zc->zc_name, buf, pos + 1); 92248498Smm } else 93248498Smm error = EINVAL; 94248498Smm /* old kernel cannot atomically destroy multiple snaps */ 95248498Smm if (!error && nvlist_next_nvpair(nvl, pair) != NULL) 96248498Smm error = EOPNOTSUPP; 97248435Smm *source = nvl; 98248435Smm break; 99248498Smm case ZFS_IOC_HOLD: 100248498Smm nvl = fnvlist_lookup_nvlist(*source, "holds"); 101248498Smm pair = nvlist_next_nvpair(nvl, NULL); 102248498Smm if (pair != NULL) { 103248498Smm buf = nvpair_name(pair); 104248498Smm pos = strcspn(buf, "@"); 105248498Smm strlcpy(zc->zc_name, buf, pos + 1); 106248498Smm strlcpy(zc->zc_value, buf + pos + 1, MAXPATHLEN); 107248498Smm if (nvpair_value_string(pair, &val) == 0) 108248498Smm strlcpy(zc->zc_string, val, MAXNAMELEN); 109248498Smm else 110248498Smm error = EINVAL; 111248498Smm } else 112248498Smm error = EINVAL; 113248498Smm /* old kernel cannot atomically create multiple holds */ 114248498Smm if (!error && nvlist_next_nvpair(nvl, pair) != NULL) 115248498Smm error = EOPNOTSUPP; 116248498Smm nvlist_free(nvl); 117248498Smm if (nvlist_lookup_int32(*source, "cleanup_fd", 118248498Smm &cleanup_fd) == 0) 119248498Smm zc->zc_cleanup_fd = cleanup_fd; 120248498Smm else 121248498Smm zc->zc_cleanup_fd = -1; 122248498Smm break; 123248498Smm case ZFS_IOC_RELEASE: 124248498Smm pair = nvlist_next_nvpair(*source, NULL); 125248498Smm if (pair != NULL) { 126248498Smm buf = nvpair_name(pair); 127248498Smm pos = strcspn(buf, "@"); 128248498Smm strlcpy(zc->zc_name, buf, pos + 1); 129248498Smm strlcpy(zc->zc_value, buf + pos + 1, MAXPATHLEN); 130248498Smm if (nvpair_value_nvlist(pair, &nvl) == 0) { 131248498Smm hpair = nvlist_next_nvpair(nvl, NULL); 132248498Smm if (hpair != NULL) 133248498Smm strlcpy(zc->zc_string, 134248498Smm nvpair_name(hpair), MAXNAMELEN); 135248498Smm else 136248498Smm error = EINVAL; 137248498Smm if (!error && nvlist_next_nvpair(nvl, 138248498Smm hpair) != NULL) 139248498Smm error = EOPNOTSUPP; 140248498Smm } else 141248498Smm error = EINVAL; 142248498Smm } else 143248498Smm error = EINVAL; 144248498Smm /* old kernel cannot atomically release multiple holds */ 145248498Smm if (!error && nvlist_next_nvpair(nvl, pair) != NULL) 146248498Smm error = EOPNOTSUPP; 147248498Smm break; 148248435Smm } 149248435Smm 150248435Smm return (error); 151248435Smm} 152248435Smm 153248435Smmvoid 154248435Smmlzc_compat_post(zfs_cmd_t *zc, const zfs_ioc_t ioc) 155248435Smm{ 156248461Smm if (zfs_ioctl_version >= ZFS_IOCVER_LZC) 157248435Smm return; 158248435Smm 159248435Smm switch (ioc) { 160248435Smm case ZFS_IOC_CREATE: 161248435Smm case ZFS_IOC_CLONE: 162248435Smm case ZFS_IOC_SNAPSHOT: 163248435Smm case ZFS_IOC_SPACE_SNAPS: 164248435Smm case ZFS_IOC_DESTROY_SNAPS: 165248435Smm zc->zc_nvlist_dst_filled = B_FALSE; 166248435Smm break; 167248435Smm } 168248435Smm} 169248435Smm 170248435Smmint 171248435Smmlzc_compat_outnvl(zfs_cmd_t *zc, const zfs_ioc_t ioc, nvlist_t **outnvl) 172248435Smm{ 173248435Smm nvlist_t *nvl; 174248435Smm 175248461Smm if (zfs_ioctl_version >= ZFS_IOCVER_LZC) 176248435Smm return (0); 177248435Smm 178248435Smm switch (ioc) { 179248435Smm case ZFS_IOC_SPACE_SNAPS: 180248435Smm nvl = fnvlist_alloc(); 181248435Smm fnvlist_add_uint64(nvl, "used", zc->zc_cookie); 182248435Smm fnvlist_add_uint64(nvl, "compressed", zc->zc_objset_type); 183248435Smm fnvlist_add_uint64(nvl, "uncompressed", zc->zc_perm_action); 184248435Smm *outnvl = nvl; 185248435Smm break; 186248435Smm } 187248435Smm 188248435Smm return (0); 189248435Smm} 190