libzfs_compat.c revision 322079
1227935Sfjoe/* 2227935Sfjoe * CDDL HEADER SART 3227935Sfjoe * 4227935Sfjoe * The contents of this file are subject to the terms of the 5227935Sfjoe * Common Development and Distribution License (the "License"). 6227935Sfjoe * You may not use this file except in compliance with the License. 7227935Sfjoe * 8227935Sfjoe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9227935Sfjoe * or http://www.opensolaris.org/os/licensing. 10227935Sfjoe * See the License for the specific language governing permissions 11227935Sfjoe * and limitations under the License. 12227935Sfjoe * 13227935Sfjoe * When distributing Covered Code, include this CDDL HEADER in each 14227935Sfjoe * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15227935Sfjoe * If applicable, add the following below this CDDL HEADER, with the 16227935Sfjoe * fields enclosed by brackets "[]" replaced with your own identifying 17227935Sfjoe * information: Portions Copyright [yyyy] [name of copyright owner] 18227935Sfjoe * 19227935Sfjoe * CDDL HEADER END 20227935Sfjoe */ 21227935Sfjoe 22227935Sfjoe/* 23227935Sfjoe * Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved. 24227935Sfjoe */ 25227935Sfjoe 26227935Sfjoe#include "libzfs_compat.h" 27227935Sfjoe 28227935Sfjoeint zfs_ioctl_version = ZFS_IOCVER_UNDEF; 29227935Sfjoestatic int zfs_spa_version = -1; 30227935Sfjoe 31227935Sfjoe/* 32227935Sfjoe * Get zfs_ioctl_version 33227935Sfjoe */ 34227935Sfjoeint 35227935Sfjoeget_zfs_ioctl_version(void) 36227935Sfjoe{ 37227935Sfjoe size_t ver_size; 38227935Sfjoe int ver = ZFS_IOCVER_NONE; 39227935Sfjoe 40228066Sfjoe ver_size = sizeof(ver); 41228066Sfjoe sysctlbyname("vfs.zfs.version.ioctl", &ver, &ver_size, NULL, 0); 42227935Sfjoe 43227935Sfjoe return (ver); 44227935Sfjoe} 45227935Sfjoe 46227935Sfjoe/* 47227935Sfjoe * Get the SPA version 48227935Sfjoe */ 49227935Sfjoestatic int 50227935Sfjoeget_zfs_spa_version(void) 51227935Sfjoe{ 52227935Sfjoe size_t ver_size; 53227935Sfjoe int ver = 0; 54227935Sfjoe 55227935Sfjoe ver_size = sizeof(ver); 56227935Sfjoe sysctlbyname("vfs.zfs.version.spa", &ver, &ver_size, NULL, 0); 57227935Sfjoe 58227937Sfjoe return (ver); 59227935Sfjoe} 60227935Sfjoe 61227935Sfjoe/* 62 * This is FreeBSD version of ioctl, because Solaris' ioctl() updates 63 * zc_nvlist_dst_size even if an error is returned, on FreeBSD if an 64 * error is returned zc_nvlist_dst_size won't be updated. 65 */ 66int 67zcmd_ioctl(int fd, int request, zfs_cmd_t *zc) 68{ 69 size_t oldsize; 70 int ret, cflag = ZFS_CMD_COMPAT_NONE; 71 72 if (zfs_ioctl_version == ZFS_IOCVER_UNDEF) 73 zfs_ioctl_version = get_zfs_ioctl_version(); 74 75 if (zfs_ioctl_version >= ZFS_IOCVER_DEADMAN) { 76 switch (zfs_ioctl_version) { 77 case ZFS_IOCVER_INLANES: 78 cflag = ZFS_CMD_COMPAT_INLANES; 79 break; 80 case ZFS_IOCVER_RESUME: 81 cflag = ZFS_CMD_COMPAT_RESUME; 82 break; 83 case ZFS_IOCVER_EDBP: 84 cflag = ZFS_CMD_COMPAT_EDBP; 85 break; 86 case ZFS_IOCVER_ZCMD: 87 cflag = ZFS_CMD_COMPAT_ZCMD; 88 break; 89 case ZFS_IOCVER_LZC: 90 cflag = ZFS_CMD_COMPAT_LZC; 91 break; 92 case ZFS_IOCVER_DEADMAN: 93 cflag = ZFS_CMD_COMPAT_DEADMAN; 94 break; 95 } 96 } else { 97 /* 98 * If vfs.zfs.version.ioctl is not defined, assume we have v28 99 * compatible binaries and use vfs.zfs.version.spa to test for v15 100 */ 101 cflag = ZFS_CMD_COMPAT_V28; 102 103 if (zfs_spa_version < 0) 104 zfs_spa_version = get_zfs_spa_version(); 105 106 if (zfs_spa_version == SPA_VERSION_15 || 107 zfs_spa_version == SPA_VERSION_14 || 108 zfs_spa_version == SPA_VERSION_13) 109 cflag = ZFS_CMD_COMPAT_V15; 110 } 111 112 oldsize = zc->zc_nvlist_dst_size; 113 ret = zcmd_ioctl_compat(fd, request, zc, cflag); 114 115 if (ret == 0 && oldsize < zc->zc_nvlist_dst_size) { 116 ret = -1; 117 errno = ENOMEM; 118 } 119 120 return (ret); 121} 122