1 // SPDX-License-Identifier: CDDL-1.0 2 /* 3 * This file and its contents are supplied under the terms of the 4 * Common Development and Distribution License ("CDDL"), version 1.0. 5 * You may only use this file in accordance with the terms of version 6 * 1.0 of the CDDL. 7 * 8 * A full copy of the text of the CDDL should have accompanied this 9 * source. A copy of the CDDL is also available via the Internet at 10 * https://opensource.org/license/CDDL-1.0. 11 */ 12 /* 13 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 14 * Copyright (c) 2012, 2017 by Delphix. All rights reserved. 15 */ 16 17 /* 18 * This file is intended for functions that ought to be common between user 19 * land (libzfs) and the kernel. When many common routines need to be shared 20 * then a separate file should be created. 21 */ 22 23 #if !defined(_KERNEL) 24 #include <string.h> 25 #endif 26 27 #include <sys/types.h> 28 #include <sys/fs/zfs.h> 29 #include <sys/nvpair.h> 30 #include "zfs_comutil.h" 31 #include <sys/zfs_ratelimit.h> 32 33 /* 34 * Are there allocatable vdevs? 35 */ 36 boolean_t 37 zfs_allocatable_devs(nvlist_t *nv) 38 { 39 uint64_t is_log; 40 uint_t c; 41 nvlist_t **child; 42 uint_t children; 43 44 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 45 &child, &children) != 0) { 46 return (B_FALSE); 47 } 48 for (c = 0; c < children; c++) { 49 is_log = 0; 50 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 51 &is_log); 52 if (!is_log) 53 return (B_TRUE); 54 } 55 return (B_FALSE); 56 } 57 58 /* 59 * Are there special vdevs? 60 */ 61 boolean_t 62 zfs_special_devs(nvlist_t *nv, const char *type) 63 { 64 const char *bias; 65 uint_t c; 66 nvlist_t **child; 67 uint_t children; 68 69 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 70 &child, &children) != 0) { 71 return (B_FALSE); 72 } 73 for (c = 0; c < children; c++) { 74 if (nvlist_lookup_string(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS, 75 &bias) == 0) { 76 if (strcmp(bias, VDEV_ALLOC_BIAS_SPECIAL) == 0 || 77 strcmp(bias, VDEV_ALLOC_BIAS_DEDUP) == 0) { 78 if (type == NULL || 79 (type != NULL && strcmp(bias, type) == 0)) 80 return (B_TRUE); 81 } 82 } 83 } 84 return (B_FALSE); 85 } 86 87 void 88 zpool_get_load_policy(nvlist_t *nvl, zpool_load_policy_t *zlpp) 89 { 90 nvlist_t *policy; 91 nvpair_t *elem; 92 const char *nm; 93 94 /* Defaults */ 95 zlpp->zlp_rewind = ZPOOL_NO_REWIND; 96 zlpp->zlp_relaxmeta = B_FALSE; 97 zlpp->zlp_maxmeta = 0; 98 zlpp->zlp_maxdata = UINT64_MAX; 99 zlpp->zlp_txg = UINT64_MAX; 100 101 if (nvl == NULL) 102 return; 103 104 elem = NULL; 105 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 106 nm = nvpair_name(elem); 107 if (strcmp(nm, ZPOOL_LOAD_POLICY) == 0) { 108 if (nvpair_value_nvlist(elem, &policy) == 0) 109 zpool_get_load_policy(policy, zlpp); 110 return; 111 } else if (strcmp(nm, ZPOOL_LOAD_REWIND_POLICY) == 0) { 112 if (nvpair_value_uint32(elem, &zlpp->zlp_rewind) == 0) 113 if (zlpp->zlp_rewind & ~ZPOOL_REWIND_POLICIES) 114 zlpp->zlp_rewind = ZPOOL_NO_REWIND; 115 } else if (strcmp(nm, ZPOOL_LOAD_REQUEST_TXG) == 0) { 116 (void) nvpair_value_uint64(elem, &zlpp->zlp_txg); 117 } else if (strcmp(nm, ZPOOL_LOAD_RELAX_META) == 0) { 118 (void) nvpair_value_boolean_value(elem, 119 &zlpp->zlp_relaxmeta); 120 } else if (strcmp(nm, ZPOOL_LOAD_META_THRESH) == 0) { 121 (void) nvpair_value_uint64(elem, &zlpp->zlp_maxmeta); 122 } else if (strcmp(nm, ZPOOL_LOAD_DATA_THRESH) == 0) { 123 (void) nvpair_value_uint64(elem, &zlpp->zlp_maxdata); 124 } 125 } 126 if (zlpp->zlp_rewind == 0) 127 zlpp->zlp_rewind = ZPOOL_NO_REWIND; 128 } 129 130 typedef struct zfs_version_spa_map { 131 int version_zpl; 132 int version_spa; 133 } zfs_version_spa_map_t; 134 135 /* 136 * Keep this table in monotonically increasing version number order. 137 */ 138 static zfs_version_spa_map_t zfs_version_table[] = { 139 {ZPL_VERSION_INITIAL, SPA_VERSION_INITIAL}, 140 {ZPL_VERSION_DIRENT_TYPE, SPA_VERSION_INITIAL}, 141 {ZPL_VERSION_FUID, SPA_VERSION_FUID}, 142 {ZPL_VERSION_USERSPACE, SPA_VERSION_USERSPACE}, 143 {ZPL_VERSION_SA, SPA_VERSION_SA}, 144 {0, 0} 145 }; 146 147 /* 148 * Return the max zpl version for a corresponding spa version 149 * -1 is returned if no mapping exists. 150 */ 151 int 152 zfs_zpl_version_map(int spa_version) 153 { 154 int version = -1; 155 156 for (int i = 0; zfs_version_table[i].version_spa; i++) 157 if (spa_version >= zfs_version_table[i].version_spa) 158 version = zfs_version_table[i].version_zpl; 159 160 return (version); 161 } 162 163 /* 164 * Return the min spa version for a corresponding spa version 165 * -1 is returned if no mapping exists. 166 */ 167 int 168 zfs_spa_version_map(int zpl_version) 169 { 170 for (int i = 0; zfs_version_table[i].version_zpl; i++) 171 if (zfs_version_table[i].version_zpl >= zpl_version) 172 return (zfs_version_table[i].version_spa); 173 174 return (-1); 175 } 176 177 /* 178 * This is the table of legacy internal event names; it should not be modified. 179 * The internal events are now stored in the history log as strings. 180 */ 181 const char *const zfs_history_event_names[ZFS_NUM_LEGACY_HISTORY_EVENTS] = { 182 "invalid event", 183 "pool create", 184 "vdev add", 185 "pool remove", 186 "pool destroy", 187 "pool export", 188 "pool import", 189 "vdev attach", 190 "vdev replace", 191 "vdev detach", 192 "vdev online", 193 "vdev offline", 194 "vdev upgrade", 195 "pool clear", 196 "pool scrub", 197 "pool property set", 198 "create", 199 "clone", 200 "destroy", 201 "destroy_begin_sync", 202 "inherit", 203 "property set", 204 "quota set", 205 "permission update", 206 "permission remove", 207 "permission who remove", 208 "promote", 209 "receive", 210 "rename", 211 "reservation set", 212 "replay_inc_sync", 213 "replay_full_sync", 214 "rollback", 215 "snapshot", 216 "filesystem version upgrade", 217 "refquota set", 218 "refreservation set", 219 "pool scrub done", 220 "user hold", 221 "user release", 222 "pool split", 223 }; 224 225 boolean_t 226 zfs_dataset_name_hidden(const char *name) 227 { 228 /* 229 * Skip over datasets that are not visible in this zone, 230 * internal datasets (which have a $ in their name), and 231 * temporary datasets (which have a % in their name). 232 */ 233 if (strpbrk(name, "$%") != NULL) 234 return (B_TRUE); 235 if (!INGLOBALZONE(curproc) && !zone_dataset_visible(name, NULL)) 236 return (B_TRUE); 237 return (B_FALSE); 238 } 239 240 #if defined(_KERNEL) 241 EXPORT_SYMBOL(zfs_allocatable_devs); 242 EXPORT_SYMBOL(zfs_special_devs); 243 EXPORT_SYMBOL(zpool_get_load_policy); 244 EXPORT_SYMBOL(zfs_zpl_version_map); 245 EXPORT_SYMBOL(zfs_spa_version_map); 246 EXPORT_SYMBOL(zfs_history_event_names); 247 EXPORT_SYMBOL(zfs_dataset_name_hidden); 248 #endif 249