libzfs_core_compat.c revision 248498
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22/* 23 * Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved. 24 */ 25 26#include <sys/zfs_ioctl.h> 27#include <zfs_ioctl_compat.h> 28#include "libzfs_core_compat.h" 29 30extern int zfs_ioctl_version; 31 32int 33lzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source) 34{ 35 nvlist_t *nvl = NULL; 36 nvpair_t *pair, *hpair; 37 char *buf, *val; 38 zfs_ioc_t vecnum; 39 uint32_t type32; 40 int32_t cleanup_fd; 41 int error = 0; 42 int pos; 43 44 if (zfs_ioctl_version >= ZFS_IOCVER_LZC) 45 return (0); 46 47 vecnum = *ioc; 48 49 switch (vecnum) { 50 case ZFS_IOC_CREATE: 51 type32 = fnvlist_lookup_int32(*source, "type"); 52 zc->zc_objset_type = (uint64_t)type32; 53 nvlist_lookup_nvlist(*source, "props", &nvl); 54 *source = nvl; 55 break; 56 case ZFS_IOC_CLONE: 57 buf = fnvlist_lookup_string(*source, "origin"); 58 strlcpy(zc->zc_value, buf, MAXPATHLEN); 59 nvlist_lookup_nvlist(*source, "props", &nvl); 60 *ioc = ZFS_IOC_CREATE; 61 *source = nvl; 62 break; 63 case ZFS_IOC_SNAPSHOT: 64 nvl = fnvlist_lookup_nvlist(*source, "snaps"); 65 pair = nvlist_next_nvpair(nvl, NULL); 66 if (pair != NULL) { 67 buf = nvpair_name(pair); 68 pos = strcspn(buf, "@"); 69 strlcpy(zc->zc_name, buf, pos + 1); 70 strlcpy(zc->zc_value, buf + pos + 1, MAXPATHLEN); 71 } else 72 error = EINVAL; 73 /* old kernel cannot create multiple snapshots */ 74 if (!error && nvlist_next_nvpair(nvl, pair) != NULL) 75 error = EOPNOTSUPP; 76 nvlist_free(nvl); 77 nvl = NULL; 78 nvlist_lookup_nvlist(*source, "props", &nvl); 79 *source = nvl; 80 break; 81 case ZFS_IOC_SPACE_SNAPS: 82 buf = fnvlist_lookup_string(*source, "firstsnap"); 83 strlcpy(zc->zc_value, buf, MAXPATHLEN); 84 break; 85 case ZFS_IOC_DESTROY_SNAPS: 86 nvl = fnvlist_lookup_nvlist(*source, "snaps"); 87 pair = nvlist_next_nvpair(nvl, NULL); 88 if (pair != NULL) { 89 buf = nvpair_name(pair); 90 pos = strcspn(buf, "@"); 91 strlcpy(zc->zc_name, buf, pos + 1); 92 } else 93 error = EINVAL; 94 /* old kernel cannot atomically destroy multiple snaps */ 95 if (!error && nvlist_next_nvpair(nvl, pair) != NULL) 96 error = EOPNOTSUPP; 97 *source = nvl; 98 break; 99 case ZFS_IOC_HOLD: 100 nvl = fnvlist_lookup_nvlist(*source, "holds"); 101 pair = nvlist_next_nvpair(nvl, NULL); 102 if (pair != NULL) { 103 buf = nvpair_name(pair); 104 pos = strcspn(buf, "@"); 105 strlcpy(zc->zc_name, buf, pos + 1); 106 strlcpy(zc->zc_value, buf + pos + 1, MAXPATHLEN); 107 if (nvpair_value_string(pair, &val) == 0) 108 strlcpy(zc->zc_string, val, MAXNAMELEN); 109 else 110 error = EINVAL; 111 } else 112 error = EINVAL; 113 /* old kernel cannot atomically create multiple holds */ 114 if (!error && nvlist_next_nvpair(nvl, pair) != NULL) 115 error = EOPNOTSUPP; 116 nvlist_free(nvl); 117 if (nvlist_lookup_int32(*source, "cleanup_fd", 118 &cleanup_fd) == 0) 119 zc->zc_cleanup_fd = cleanup_fd; 120 else 121 zc->zc_cleanup_fd = -1; 122 break; 123 case ZFS_IOC_RELEASE: 124 pair = nvlist_next_nvpair(*source, NULL); 125 if (pair != NULL) { 126 buf = nvpair_name(pair); 127 pos = strcspn(buf, "@"); 128 strlcpy(zc->zc_name, buf, pos + 1); 129 strlcpy(zc->zc_value, buf + pos + 1, MAXPATHLEN); 130 if (nvpair_value_nvlist(pair, &nvl) == 0) { 131 hpair = nvlist_next_nvpair(nvl, NULL); 132 if (hpair != NULL) 133 strlcpy(zc->zc_string, 134 nvpair_name(hpair), MAXNAMELEN); 135 else 136 error = EINVAL; 137 if (!error && nvlist_next_nvpair(nvl, 138 hpair) != NULL) 139 error = EOPNOTSUPP; 140 } else 141 error = EINVAL; 142 } else 143 error = EINVAL; 144 /* old kernel cannot atomically release multiple holds */ 145 if (!error && nvlist_next_nvpair(nvl, pair) != NULL) 146 error = EOPNOTSUPP; 147 break; 148 } 149 150 return (error); 151} 152 153void 154lzc_compat_post(zfs_cmd_t *zc, const zfs_ioc_t ioc) 155{ 156 if (zfs_ioctl_version >= ZFS_IOCVER_LZC) 157 return; 158 159 switch (ioc) { 160 case ZFS_IOC_CREATE: 161 case ZFS_IOC_CLONE: 162 case ZFS_IOC_SNAPSHOT: 163 case ZFS_IOC_SPACE_SNAPS: 164 case ZFS_IOC_DESTROY_SNAPS: 165 zc->zc_nvlist_dst_filled = B_FALSE; 166 break; 167 } 168} 169 170int 171lzc_compat_outnvl(zfs_cmd_t *zc, const zfs_ioc_t ioc, nvlist_t **outnvl) 172{ 173 nvlist_t *nvl; 174 175 if (zfs_ioctl_version >= ZFS_IOCVER_LZC) 176 return (0); 177 178 switch (ioc) { 179 case ZFS_IOC_SPACE_SNAPS: 180 nvl = fnvlist_alloc(); 181 fnvlist_add_uint64(nvl, "used", zc->zc_cookie); 182 fnvlist_add_uint64(nvl, "compressed", zc->zc_objset_type); 183 fnvlist_add_uint64(nvl, "uncompressed", zc->zc_perm_action); 184 *outnvl = nvl; 185 break; 186 } 187 188 return (0); 189} 190