diff options
Diffstat (limited to 'sys/contrib/openzfs/module/zcommon/zfs_comutil.c')
-rw-r--r-- | sys/contrib/openzfs/module/zcommon/zfs_comutil.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/sys/contrib/openzfs/module/zcommon/zfs_comutil.c b/sys/contrib/openzfs/module/zcommon/zfs_comutil.c new file mode 100644 index 000000000000..85eee4f21c3e --- /dev/null +++ b/sys/contrib/openzfs/module/zcommon/zfs_comutil.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: CDDL-1.0 +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or https://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 by Delphix. All rights reserved. + */ + +/* + * This file is intended for functions that ought to be common between user + * land (libzfs) and the kernel. When many common routines need to be shared + * then a separate file should be created. + */ + +#if !defined(_KERNEL) +#include <string.h> +#endif + +#include <sys/types.h> +#include <sys/fs/zfs.h> +#include <sys/nvpair.h> +#include "zfs_comutil.h" +#include <sys/zfs_ratelimit.h> + +/* + * Are there allocatable vdevs? + */ +boolean_t +zfs_allocatable_devs(nvlist_t *nv) +{ + uint64_t is_log; + uint_t c; + nvlist_t **child; + uint_t children; + + if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, + &child, &children) != 0) { + return (B_FALSE); + } + for (c = 0; c < children; c++) { + is_log = 0; + (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, + &is_log); + if (!is_log) + return (B_TRUE); + } + return (B_FALSE); +} + +/* + * Are there special vdevs? + */ +boolean_t +zfs_special_devs(nvlist_t *nv, const char *type) +{ + const char *bias; + uint_t c; + nvlist_t **child; + uint_t children; + + if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, + &child, &children) != 0) { + return (B_FALSE); + } + for (c = 0; c < children; c++) { + if (nvlist_lookup_string(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS, + &bias) == 0) { + if (strcmp(bias, VDEV_ALLOC_BIAS_SPECIAL) == 0 || + strcmp(bias, VDEV_ALLOC_BIAS_DEDUP) == 0) { + if (type == NULL || + (type != NULL && strcmp(bias, type) == 0)) + return (B_TRUE); + } + } + } + return (B_FALSE); +} + +void +zpool_get_load_policy(nvlist_t *nvl, zpool_load_policy_t *zlpp) +{ + nvlist_t *policy; + nvpair_t *elem; + const char *nm; + + /* Defaults */ + zlpp->zlp_rewind = ZPOOL_NO_REWIND; + zlpp->zlp_maxmeta = 0; + zlpp->zlp_maxdata = UINT64_MAX; + zlpp->zlp_txg = UINT64_MAX; + + if (nvl == NULL) + return; + + elem = NULL; + while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { + nm = nvpair_name(elem); + if (strcmp(nm, ZPOOL_LOAD_POLICY) == 0) { + if (nvpair_value_nvlist(elem, &policy) == 0) + zpool_get_load_policy(policy, zlpp); + return; + } else if (strcmp(nm, ZPOOL_LOAD_REWIND_POLICY) == 0) { + if (nvpair_value_uint32(elem, &zlpp->zlp_rewind) == 0) + if (zlpp->zlp_rewind & ~ZPOOL_REWIND_POLICIES) + zlpp->zlp_rewind = ZPOOL_NO_REWIND; + } else if (strcmp(nm, ZPOOL_LOAD_REQUEST_TXG) == 0) { + (void) nvpair_value_uint64(elem, &zlpp->zlp_txg); + } else if (strcmp(nm, ZPOOL_LOAD_META_THRESH) == 0) { + (void) nvpair_value_uint64(elem, &zlpp->zlp_maxmeta); + } else if (strcmp(nm, ZPOOL_LOAD_DATA_THRESH) == 0) { + (void) nvpair_value_uint64(elem, &zlpp->zlp_maxdata); + } + } + if (zlpp->zlp_rewind == 0) + zlpp->zlp_rewind = ZPOOL_NO_REWIND; +} + +typedef struct zfs_version_spa_map { + int version_zpl; + int version_spa; +} zfs_version_spa_map_t; + +/* + * Keep this table in monotonically increasing version number order. + */ +static zfs_version_spa_map_t zfs_version_table[] = { + {ZPL_VERSION_INITIAL, SPA_VERSION_INITIAL}, + {ZPL_VERSION_DIRENT_TYPE, SPA_VERSION_INITIAL}, + {ZPL_VERSION_FUID, SPA_VERSION_FUID}, + {ZPL_VERSION_USERSPACE, SPA_VERSION_USERSPACE}, + {ZPL_VERSION_SA, SPA_VERSION_SA}, + {0, 0} +}; + +/* + * Return the max zpl version for a corresponding spa version + * -1 is returned if no mapping exists. + */ +int +zfs_zpl_version_map(int spa_version) +{ + int version = -1; + + for (int i = 0; zfs_version_table[i].version_spa; i++) + if (spa_version >= zfs_version_table[i].version_spa) + version = zfs_version_table[i].version_zpl; + + return (version); +} + +/* + * Return the min spa version for a corresponding spa version + * -1 is returned if no mapping exists. + */ +int +zfs_spa_version_map(int zpl_version) +{ + for (int i = 0; zfs_version_table[i].version_zpl; i++) + if (zfs_version_table[i].version_zpl >= zpl_version) + return (zfs_version_table[i].version_spa); + + return (-1); +} + +/* + * This is the table of legacy internal event names; it should not be modified. + * The internal events are now stored in the history log as strings. + */ +const char *const zfs_history_event_names[ZFS_NUM_LEGACY_HISTORY_EVENTS] = { + "invalid event", + "pool create", + "vdev add", + "pool remove", + "pool destroy", + "pool export", + "pool import", + "vdev attach", + "vdev replace", + "vdev detach", + "vdev online", + "vdev offline", + "vdev upgrade", + "pool clear", + "pool scrub", + "pool property set", + "create", + "clone", + "destroy", + "destroy_begin_sync", + "inherit", + "property set", + "quota set", + "permission update", + "permission remove", + "permission who remove", + "promote", + "receive", + "rename", + "reservation set", + "replay_inc_sync", + "replay_full_sync", + "rollback", + "snapshot", + "filesystem version upgrade", + "refquota set", + "refreservation set", + "pool scrub done", + "user hold", + "user release", + "pool split", +}; + +boolean_t +zfs_dataset_name_hidden(const char *name) +{ + /* + * Skip over datasets that are not visible in this zone, + * internal datasets (which have a $ in their name), and + * temporary datasets (which have a % in their name). + */ + if (strpbrk(name, "$%") != NULL) + return (B_TRUE); + if (!INGLOBALZONE(curproc) && !zone_dataset_visible(name, NULL)) + return (B_TRUE); + return (B_FALSE); +} + +#if defined(_KERNEL) +EXPORT_SYMBOL(zfs_allocatable_devs); +EXPORT_SYMBOL(zfs_special_devs); +EXPORT_SYMBOL(zpool_get_load_policy); +EXPORT_SYMBOL(zfs_zpl_version_map); +EXPORT_SYMBOL(zfs_spa_version_map); +EXPORT_SYMBOL(zfs_history_event_names); +EXPORT_SYMBOL(zfs_dataset_name_hidden); +#endif |