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 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This file is intended for functions that ought to be common between user 28 * land (libzfs) and the kernel. When many common routines need to be shared 29 * then a separate file should to be created. 30 */ 31 32 #if defined(_KERNEL) 33 #include <sys/systm.h> 34 #else 35 #include <string.h> 36 #endif 37 38 #include <sys/types.h> 39 #include <sys/fs/zfs.h> 40 #include <sys/int_limits.h> 41 #include <sys/nvpair.h> 42 #include "zfs_comutil.h" 43 44 /* 45 * Are there allocatable vdevs? 46 */ 47 boolean_t 48 zfs_allocatable_devs(nvlist_t *nv) 49 { 50 uint64_t is_log; 51 uint_t c; 52 nvlist_t **child; 53 uint_t children; 54 55 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 56 &child, &children) != 0) { 57 return (B_FALSE); 58 } 59 for (c = 0; c < children; c++) { 60 is_log = 0; 61 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 62 &is_log); 63 if (!is_log) 64 return (B_TRUE); 65 } 66 return (B_FALSE); 67 } 68 69 void 70 zpool_get_rewind_policy(nvlist_t *nvl, zpool_rewind_policy_t *zrpp) 71 { 72 nvlist_t *policy; 73 nvpair_t *elem; 74 char *nm; 75 76 /* Defaults */ 77 zrpp->zrp_request = ZPOOL_NO_REWIND; 78 zrpp->zrp_maxmeta = 0; 79 zrpp->zrp_maxdata = UINT64_MAX; 80 zrpp->zrp_txg = UINT64_MAX; 81 82 if (nvl == NULL) 83 return; 84 85 elem = NULL; 86 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 87 nm = nvpair_name(elem); 88 if (strcmp(nm, ZPOOL_REWIND_POLICY) == 0) { 89 if (nvpair_value_nvlist(elem, &policy) == 0) 90 zpool_get_rewind_policy(policy, zrpp); 91 return; 92 } else if (strcmp(nm, ZPOOL_REWIND_REQUEST) == 0) { 93 if (nvpair_value_uint32(elem, &zrpp->zrp_request) == 0) 94 if (zrpp->zrp_request & ~ZPOOL_REWIND_POLICIES) 95 zrpp->zrp_request = ZPOOL_NO_REWIND; 96 } else if (strcmp(nm, ZPOOL_REWIND_REQUEST_TXG) == 0) { 97 (void) nvpair_value_uint64(elem, &zrpp->zrp_txg); 98 } else if (strcmp(nm, ZPOOL_REWIND_META_THRESH) == 0) { 99 (void) nvpair_value_uint64(elem, &zrpp->zrp_maxmeta); 100 } else if (strcmp(nm, ZPOOL_REWIND_DATA_THRESH) == 0) { 101 (void) nvpair_value_uint64(elem, &zrpp->zrp_maxdata); 102 } 103 } 104 if (zrpp->zrp_request == 0) 105 zrpp->zrp_request = ZPOOL_NO_REWIND; 106 } 107 108 typedef struct zfs_version_spa_map { 109 int version_zpl; 110 int version_spa; 111 } zfs_version_spa_map_t; 112 113 /* 114 * Keep this table in monotonically increasing version number order. 115 */ 116 static zfs_version_spa_map_t zfs_version_table[] = { 117 {ZPL_VERSION_INITIAL, SPA_VERSION_INITIAL}, 118 {ZPL_VERSION_DIRENT_TYPE, SPA_VERSION_INITIAL}, 119 {ZPL_VERSION_FUID, SPA_VERSION_FUID}, 120 {ZPL_VERSION_USERSPACE, SPA_VERSION_USERSPACE}, 121 {ZPL_VERSION_SA, SPA_VERSION_SA}, 122 {0, 0} 123 }; 124 125 /* 126 * Return the max zpl version for a corresponding spa version 127 * -1 is returned if no mapping exists. 128 */ 129 int 130 zfs_zpl_version_map(int spa_version) 131 { 132 int i; 133 int version = -1; 134 135 for (i = 0; zfs_version_table[i].version_spa; i++) { 136 if (spa_version >= zfs_version_table[i].version_spa) 137 version = zfs_version_table[i].version_zpl; 138 } 139 140 return (version); 141 } 142 143 /* 144 * Return the min spa version for a corresponding spa version 145 * -1 is returned if no mapping exists. 146 */ 147 int 148 zfs_spa_version_map(int zpl_version) 149 { 150 int i; 151 int version = -1; 152 153 for (i = 0; zfs_version_table[i].version_zpl; i++) { 154 if (zfs_version_table[i].version_zpl >= zpl_version) 155 return (zfs_version_table[i].version_spa); 156 } 157 158 return (version); 159 } 160