diff options
Diffstat (limited to 'sys/contrib/openzfs/lib')
32 files changed, 1334 insertions, 317 deletions
diff --git a/sys/contrib/openzfs/lib/libicp/Makefile.am b/sys/contrib/openzfs/lib/libicp/Makefile.am index ce24d13a760f..23adba10bc44 100644 --- a/sys/contrib/openzfs/lib/libicp/Makefile.am +++ b/sys/contrib/openzfs/lib/libicp/Makefile.am @@ -69,6 +69,7 @@ nodist_libicp_la_SOURCES += \ module/icp/asm-x86_64/aes/aes_aesni.S \ module/icp/asm-x86_64/modes/gcm_pclmulqdq.S \ module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S \ + module/icp/asm-x86_64/modes/aesni-gcm-avx2-vaes.S \ module/icp/asm-x86_64/modes/ghash-x86_64.S \ module/icp/asm-x86_64/sha2/sha256-x86_64.S \ module/icp/asm-x86_64/sha2/sha512-x86_64.S \ diff --git a/sys/contrib/openzfs/lib/libspl/Makefile.am b/sys/contrib/openzfs/lib/libspl/Makefile.am index f8943572bf29..0fd907d3011e 100644 --- a/sys/contrib/openzfs/lib/libspl/Makefile.am +++ b/sys/contrib/openzfs/lib/libspl/Makefile.am @@ -2,6 +2,9 @@ include $(srcdir)/%D%/include/Makefile.am libspl_assert_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS) $(LIBUNWIND_CFLAGS) libspl_la_CFLAGS = $(libspl_assert_la_CFLAGS) +if TARGET_CPU_I386 +libspl_la_CFLAGS += $(NO_ATOMIC_ALIGNMENT) +endif noinst_LTLIBRARIES += libspl_assert.la libspl.la CPPCHECKTARGETS += libspl_assert.la libspl.la @@ -20,6 +23,7 @@ libspl_la_SOURCES = \ %D%/strlcat.c \ %D%/strlcpy.c \ %D%/timestamp.c \ + %D%/tunables.c \ %D%/include/sys/list.h \ %D%/include/sys/list_impl.h diff --git a/sys/contrib/openzfs/lib/libspl/include/Makefile.am b/sys/contrib/openzfs/lib/libspl/include/Makefile.am index 8c286142f298..21f0c70db9e7 100644 --- a/sys/contrib/openzfs/lib/libspl/include/Makefile.am +++ b/sys/contrib/openzfs/lib/libspl/include/Makefile.am @@ -45,6 +45,7 @@ libspl_sys_HEADERS = \ %D%/sys/list_impl.h \ %D%/sys/mhd.h \ %D%/sys/mkdev.h \ + %D%/sys/mod.h \ %D%/sys/policy.h \ %D%/sys/poll.h \ %D%/sys/priv.h \ @@ -58,6 +59,7 @@ libspl_sys_HEADERS = \ %D%/sys/time.h \ %D%/sys/trace_spl.h \ %D%/sys/trace_zfs.h \ + %D%/sys/tunables.h \ %D%/sys/types.h \ %D%/sys/types32.h \ %D%/sys/uio.h \ diff --git a/sys/contrib/openzfs/lib/libspl/include/os/linux/sys/stat.h b/sys/contrib/openzfs/lib/libspl/include/os/linux/sys/stat.h index 488554f4e844..13cc0b46ac93 100644 --- a/sys/contrib/openzfs/lib/libspl/include/os/linux/sys/stat.h +++ b/sys/contrib/openzfs/lib/libspl/include/os/linux/sys/stat.h @@ -31,6 +31,11 @@ #include <sys/mount.h> /* for BLKGETSIZE64 */ +#ifdef HAVE_STATX +#include <fcntl.h> +#include <sys/stat.h> +#endif + /* * Emulate Solaris' behavior of returning the block device size in fstat64(). */ diff --git a/sys/contrib/openzfs/lib/libspl/include/sys/debug.h b/sys/contrib/openzfs/lib/libspl/include/sys/debug.h index cced309bd1bb..02f33a68b75b 100644 --- a/sys/contrib/openzfs/lib/libspl/include/sys/debug.h +++ b/sys/contrib/openzfs/lib/libspl/include/sys/debug.h @@ -38,4 +38,8 @@ #define __maybe_unused __attribute__((unused)) #endif +#ifndef __must_check +#define __must_check __attribute__((warn_unused_result)) +#endif + #endif diff --git a/sys/contrib/openzfs/lib/libspl/include/sys/mod.h b/sys/contrib/openzfs/lib/libspl/include/sys/mod.h new file mode 100644 index 000000000000..ad19b6607a42 --- /dev/null +++ b/sys/contrib/openzfs/lib/libspl/include/sys/mod.h @@ -0,0 +1,56 @@ +// 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) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2012, 2018 by Delphix. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2025, Rob Norris <robn@despairlabs.com> + */ + +#ifndef _SYS_MOD_H +#define _SYS_MOD_H + +#include <sys/tunables.h> + +#define ZFS_MODULE_PARAM(scope, prefix, name, type, perm, desc) \ + static const zfs_tunable_t _zfs_tunable_##prefix##name = { \ + .zt_name = #prefix#name, \ + .zt_varp = &prefix##name, \ + .zt_varsz = sizeof (prefix##name), \ + .zt_type = ZFS_TUNABLE_TYPE_##type, \ + .zt_perm = ZFS_TUNABLE_PERM_##perm, \ + .zt_desc = desc \ + }; \ + static const zfs_tunable_t * \ + __zfs_tunable_##prefix##name \ + __attribute__((__section__("zfs_tunables"))) \ + __attribute__((__used__)) \ + = &_zfs_tunable_##prefix##name; + +#define ZFS_MODULE_PARAM_ARGS void +#define ZFS_MODULE_PARAM_CALL(scope_prefix, name_prefix, name, setfunc, \ + getfunc, perm, desc) + +#define EXPORT_SYMBOL(x) + +#endif diff --git a/sys/contrib/openzfs/lib/libspl/include/sys/simd.h b/sys/contrib/openzfs/lib/libspl/include/sys/simd.h index 1ef24f5a7d39..4772a5416b2e 100644 --- a/sys/contrib/openzfs/lib/libspl/include/sys/simd.h +++ b/sys/contrib/openzfs/lib/libspl/include/sys/simd.h @@ -102,7 +102,9 @@ typedef enum cpuid_inst_sets { AES, PCLMULQDQ, MOVBE, - SHA_NI + SHA_NI, + VAES, + VPCLMULQDQ } cpuid_inst_sets_t; /* @@ -127,6 +129,8 @@ typedef struct cpuid_feature_desc { #define _AES_BIT (1U << 25) #define _PCLMULQDQ_BIT (1U << 1) #define _MOVBE_BIT (1U << 22) +#define _VAES_BIT (1U << 9) +#define _VPCLMULQDQ_BIT (1U << 10) #define _SHA_NI_BIT (1U << 29) /* @@ -157,6 +161,8 @@ static const cpuid_feature_desc_t cpuid_features[] = { [PCLMULQDQ] = {1U, 0U, _PCLMULQDQ_BIT, ECX }, [MOVBE] = {1U, 0U, _MOVBE_BIT, ECX }, [SHA_NI] = {7U, 0U, _SHA_NI_BIT, EBX }, + [VAES] = {7U, 0U, _VAES_BIT, ECX }, + [VPCLMULQDQ] = {7U, 0U, _VPCLMULQDQ_BIT, ECX }, }; /* @@ -231,6 +237,8 @@ CPUID_FEATURE_CHECK(aes, AES); CPUID_FEATURE_CHECK(pclmulqdq, PCLMULQDQ); CPUID_FEATURE_CHECK(movbe, MOVBE); CPUID_FEATURE_CHECK(shani, SHA_NI); +CPUID_FEATURE_CHECK(vaes, VAES); +CPUID_FEATURE_CHECK(vpclmulqdq, VPCLMULQDQ); /* * Detect register set support @@ -382,6 +390,24 @@ zfs_shani_available(void) } /* + * Check if VAES instruction is available + */ +static inline boolean_t +zfs_vaes_available(void) +{ + return (__cpuid_has_vaes()); +} + +/* + * Check if VPCLMULQDQ instruction is available + */ +static inline boolean_t +zfs_vpclmulqdq_available(void) +{ + return (__cpuid_has_vpclmulqdq()); +} + +/* * AVX-512 family of instruction sets: * * AVX512F Foundation diff --git a/sys/contrib/openzfs/lib/libspl/include/sys/time.h b/sys/contrib/openzfs/lib/libspl/include/sys/time.h index da80a5852ae5..062c6ec979fc 100644 --- a/sys/contrib/openzfs/lib/libspl/include/sys/time.h +++ b/sys/contrib/openzfs/lib/libspl/include/sys/time.h @@ -98,6 +98,15 @@ gethrestime_sec(void) } static inline hrtime_t +getlrtime(void) +{ + struct timeval tv; + (void) gettimeofday(&tv, NULL); + return ((((uint64_t)tv.tv_sec) * NANOSEC) + + ((uint64_t)tv.tv_usec * NSEC_PER_USEC)); +} + +static inline hrtime_t gethrtime(void) { struct timespec ts; diff --git a/sys/contrib/openzfs/lib/libspl/include/sys/tunables.h b/sys/contrib/openzfs/lib/libspl/include/sys/tunables.h new file mode 100644 index 000000000000..5d9bb3d71a4a --- /dev/null +++ b/sys/contrib/openzfs/lib/libspl/include/sys/tunables.h @@ -0,0 +1,60 @@ +// 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) 2025, Rob Norris <robn@despairlabs.com> + */ + +#ifndef _SYS_TUNABLES_H +#define _SYS_TUNABLES_H + +typedef enum { + ZFS_TUNABLE_TYPE_INT, + ZFS_TUNABLE_TYPE_UINT, + ZFS_TUNABLE_TYPE_ULONG, + ZFS_TUNABLE_TYPE_U64, + ZFS_TUNABLE_TYPE_STRING, +} zfs_tunable_type_t; + +typedef enum { + ZFS_TUNABLE_PERM_ZMOD_RW, + ZFS_TUNABLE_PERM_ZMOD_RD, +} zfs_tunable_perm_t; + +typedef struct zfs_tunable { + const char *zt_name; + void *zt_varp; + size_t zt_varsz; + zfs_tunable_type_t zt_type; + zfs_tunable_perm_t zt_perm; + const char *zt_desc; +} zfs_tunable_t; + +int zfs_tunable_set(const zfs_tunable_t *tunable, const char *val); +int zfs_tunable_get(const zfs_tunable_t *tunable, char *val, size_t valsz); + +const zfs_tunable_t *zfs_tunable_lookup(const char *name); + +typedef int (*zfs_tunable_iter_t)(const zfs_tunable_t *tunable, void *arg); +void zfs_tunable_iter(zfs_tunable_iter_t cb, void *arg); + +#endif diff --git a/sys/contrib/openzfs/lib/libspl/include/sys/uio.h b/sys/contrib/openzfs/lib/libspl/include/sys/uio.h index 93aa4984d734..9ada482be000 100644 --- a/sys/contrib/openzfs/lib/libspl/include/sys/uio.h +++ b/sys/contrib/openzfs/lib/libspl/include/sys/uio.h @@ -41,6 +41,7 @@ #ifndef _LIBSPL_SYS_UIO_H #define _LIBSPL_SYS_UIO_H +#include <sys/sysmacros.h> #include <sys/types.h> #include_next <sys/uio.h> diff --git a/sys/contrib/openzfs/lib/libspl/include/umem.h b/sys/contrib/openzfs/lib/libspl/include/umem.h index 6945aae9f3ce..3e44610e4e21 100644 --- a/sys/contrib/openzfs/lib/libspl/include/umem.h +++ b/sys/contrib/openzfs/lib/libspl/include/umem.h @@ -102,7 +102,7 @@ static inline void * umem_alloc_aligned(size_t size, size_t align, int flags) { void *ptr = NULL; - int rc = EINVAL; + int rc; do { rc = posix_memalign(&ptr, align, size); diff --git a/sys/contrib/openzfs/lib/libspl/os/linux/getmntany.c b/sys/contrib/openzfs/lib/libspl/os/linux/getmntany.c index dcdf7b3d6fc9..ee1cdf59b9e5 100644 --- a/sys/contrib/openzfs/lib/libspl/os/linux/getmntany.c +++ b/sys/contrib/openzfs/lib/libspl/os/linux/getmntany.c @@ -85,13 +85,21 @@ _sol_getmntent(FILE *fp, struct mnttab *mgetp) } static int -getextmntent_impl(FILE *fp, struct extmnttab *mp) +getextmntent_impl(FILE *fp, struct extmnttab *mp, uint64_t *mnt_id) { int ret; struct stat64 st; + *mnt_id = 0; ret = _sol_getmntent(fp, (struct mnttab *)mp); if (ret == 0) { +#ifdef HAVE_STATX_MNT_ID + struct statx stx; + if (statx(AT_FDCWD, mp->mnt_mountp, + AT_STATX_SYNC_AS_STAT | AT_SYMLINK_NOFOLLOW, + STATX_MNT_ID, &stx) == 0 && (stx.stx_mask & STATX_MNT_ID)) + *mnt_id = stx.stx_mnt_id; +#endif if (stat64(mp->mnt_mountp, &st) != 0) { mp->mnt_major = 0; mp->mnt_minor = 0; @@ -110,6 +118,12 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf) struct stat64 st; FILE *fp; int match; + boolean_t have_mnt_id = B_FALSE; + uint64_t target_mnt_id = 0; + uint64_t entry_mnt_id; +#ifdef HAVE_STATX_MNT_ID + struct statx stx; +#endif if (strlen(path) >= MAXPATHLEN) { (void) fprintf(stderr, "invalid object; pathname too long\n"); @@ -128,6 +142,13 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf) return (-1); } +#ifdef HAVE_STATX_MNT_ID + if (statx(AT_FDCWD, path, AT_STATX_SYNC_AS_STAT | AT_SYMLINK_NOFOLLOW, + STATX_MNT_ID, &stx) == 0 && (stx.stx_mask & STATX_MNT_ID)) { + have_mnt_id = B_TRUE; + target_mnt_id = stx.stx_mnt_id; + } +#endif if ((fp = fopen(MNTTAB, "re")) == NULL) { (void) fprintf(stderr, "cannot open %s\n", MNTTAB); @@ -139,12 +160,15 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf) */ match = 0; - while (getextmntent_impl(fp, entry) == 0) { - if (makedev(entry->mnt_major, entry->mnt_minor) == - statbuf->st_dev) { - match = 1; - break; + while (getextmntent_impl(fp, entry, &entry_mnt_id) == 0) { + if (have_mnt_id) { + match = (entry_mnt_id == target_mnt_id); + } else { + match = makedev(entry->mnt_major, entry->mnt_minor) == + statbuf->st_dev; } + if (match) + break; } (void) fclose(fp); diff --git a/sys/contrib/openzfs/lib/libspl/tunables.c b/sys/contrib/openzfs/lib/libspl/tunables.c new file mode 100644 index 000000000000..67dc9710dee8 --- /dev/null +++ b/sys/contrib/openzfs/lib/libspl/tunables.c @@ -0,0 +1,319 @@ +// 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) 2025, Rob Norris <robn@despairlabs.com> + */ + +#include <stddef.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <limits.h> +#include <inttypes.h> +#include <sys/tunables.h> + +/* + * Userspace tunables. + * + * Tunables are external pointers to global variables that are wired up to the + * host environment in some way that allows the operator to directly change + * their values "under the hood". + * + * In userspace, the "host environment" is the program using libzpool.so. So + * that it can manipulate tunables if it wants, we provide an API to access + * them. + * + * Tunables are declared through the ZFS_MODULE_PARAM* macros, which associate + * a global variable with some metadata we can use to describe and access the + * tunable. This is done by creating a uniquely-named zfs_tunable_t. + * + * At runtime, we need a way to discover these zfs_tunable_t items. Since they + * are declared globally, all over the codebase, there's no central place to + * record or list them. So, we take advantage of the compiler's "linker set" + * feature. + * + * In the ZFS_MODULE_PARAM macro, after we create the zfs_tunable_t, we also + * create a zfs_tunable_t* pointing to it. That pointer is forced into the + * "zfs_tunables" ELF section in compiled object. At link time, the linker will + * collect all these pointers into one single big "zfs_tunable" section, and + * will generate two new symbols in the final object: __start_zfs_tunable and + * __stop_zfs_tunable. These point to the first and last item in that section, + * which allows us to access the pointers in that section like an array, and + * through those pointers access the tunable metadata, and from there the + * actual C variable that the tunable describes. + */ + +extern const zfs_tunable_t *__start_zfs_tunables; +extern const zfs_tunable_t *__stop_zfs_tunables; + +/* + * Because there are no tunables in libspl itself, the above symbols will not + * be generated, which will stop libspl being linked at all. To work around + * that, we force a symbol into that section, and then when iterating, skip + * any NULL pointers. + */ +static void *__zfs_tunable__placeholder + __attribute__((__section__("zfs_tunables"))) + __attribute__((__used__)) = NULL; + +/* + * Find the name tunable by walking through the linker set and comparing names, + * as described above. This is not particularly efficient but it's a fairly + * rare task, so it shouldn't be a big deal. + */ +const zfs_tunable_t * +zfs_tunable_lookup(const char *name) +{ + for (const zfs_tunable_t **ztp = &__start_zfs_tunables; + ztp != &__stop_zfs_tunables; ztp++) { + const zfs_tunable_t *zt = *ztp; + if (zt == NULL) + continue; + if (strcmp(name, zt->zt_name) == 0) + return (zt); + } + + return (NULL); +} + +/* + * Like zfs_tunable_lookup, but call the provided callback for each tunable. + */ +void +zfs_tunable_iter(zfs_tunable_iter_t cb, void *arg) +{ + for (const zfs_tunable_t **ztp = &__start_zfs_tunables; + ztp != &__stop_zfs_tunables; ztp++) { + const zfs_tunable_t *zt = *ztp; + if (zt == NULL) + continue; + if (cb(zt, arg)) + return; + } +} + +/* + * Parse a string into an int or uint. It's easier to have a pair of "generic" + * functions that clamp to a given min and max rather than have multiple + * functions for each width of type. + */ +static int +zfs_tunable_parse_int(const char *val, intmax_t *np, + intmax_t min, intmax_t max) +{ + intmax_t n; + char *end; + errno = 0; + n = strtoimax(val, &end, 0); + if (errno != 0) + return (errno); + if (*end != '\0') + return (EINVAL); + if (n < min || n > max) + return (ERANGE); + *np = n; + return (0); +} + +static int +zfs_tunable_parse_uint(const char *val, uintmax_t *np, + uintmax_t min, uintmax_t max) +{ + uintmax_t n; + char *end; + errno = 0; + n = strtoumax(val, &end, 0); + if (errno != 0) + return (errno); + if (*end != '\0') + return (EINVAL); + if (strchr(val, '-')) + return (ERANGE); + if (n < min || n > max) + return (ERANGE); + *np = n; + return (0); +} + +/* + * Set helpers for each tunable type. Parses the string, and if produces a + * valid value for the tunable, sets it. No effort is made to make sure the + * tunable is of the right type; that's done in zfs_tunable_set() below. + */ +static int +zfs_tunable_set_int(const zfs_tunable_t *zt, const char *val) +{ + intmax_t n; + int err = zfs_tunable_parse_int(val, &n, INT_MIN, INT_MAX); + if (err != 0) + return (err); + *(int *)zt->zt_varp = n; + return (0); +} + +static int +zfs_tunable_set_uint(const zfs_tunable_t *zt, const char *val) +{ + uintmax_t n; + int err = zfs_tunable_parse_uint(val, &n, 0, UINT_MAX); + if (err != 0) + return (err); + *(unsigned int *)zt->zt_varp = n; + return (0); +} + +static int +zfs_tunable_set_ulong(const zfs_tunable_t *zt, const char *val) +{ + uintmax_t n; + int err = zfs_tunable_parse_uint(val, &n, 0, ULONG_MAX); + if (err != 0) + return (err); + *(unsigned long *)zt->zt_varp = n; + return (0); +} + +static int +zfs_tunable_set_u64(const zfs_tunable_t *zt, const char *val) +{ + uintmax_t n; + int err = zfs_tunable_parse_uint(val, &n, 0, UINT64_MAX); + if (err != 0) + return (err); + *(uint64_t *)zt->zt_varp = n; + return (0); +} + +static int +zfs_tunable_set_string(const zfs_tunable_t *zt, const char *val) +{ + (void) zt, (void) val; + /* + * We can't currently handle strings. String tunables are pointers + * into read-only memory, so we can update the pointer, but not the + * contents. That would mean taking an allocation, but we don't have + * an obvious place to free it. + * + * For now, it's no big deal as there's only a couple of string + * tunables anyway. + */ + return (ENOTSUP); +} + +/* + * Get helpers for each tunable type. Converts the value to a string if + * necessary and writes it into the provided buffer. The type is assumed to + * be correct; zfs_tunable_get() below will call the correct function for the + * type. + */ +static int +zfs_tunable_get_int(const zfs_tunable_t *zt, char *val, size_t valsz) +{ + snprintf(val, valsz, "%d", *(int *)zt->zt_varp); + return (0); +} + +static int +zfs_tunable_get_uint(const zfs_tunable_t *zt, char *val, size_t valsz) +{ + snprintf(val, valsz, "%u", *(unsigned int *)zt->zt_varp); + return (0); +} + +static int +zfs_tunable_get_ulong(const zfs_tunable_t *zt, char *val, size_t valsz) +{ + snprintf(val, valsz, "%lu", *(unsigned long *)zt->zt_varp); + return (0); +} + +static int +zfs_tunable_get_u64(const zfs_tunable_t *zt, char *val, size_t valsz) +{ + snprintf(val, valsz, "%"PRIu64, *(uint64_t *)zt->zt_varp); + return (0); +} + +static int +zfs_tunable_get_string(const zfs_tunable_t *zt, char *val, size_t valsz) +{ + strlcpy(val, *(char **)zt->zt_varp, valsz); + return (0); +} + +/* The public set function. Delegates to the type-specific version. */ +int +zfs_tunable_set(const zfs_tunable_t *zt, const char *val) +{ + int err; + switch (zt->zt_type) { + case ZFS_TUNABLE_TYPE_INT: + err = zfs_tunable_set_int(zt, val); + break; + case ZFS_TUNABLE_TYPE_UINT: + err = zfs_tunable_set_uint(zt, val); + break; + case ZFS_TUNABLE_TYPE_ULONG: + err = zfs_tunable_set_ulong(zt, val); + break; + case ZFS_TUNABLE_TYPE_U64: + err = zfs_tunable_set_u64(zt, val); + break; + case ZFS_TUNABLE_TYPE_STRING: + err = zfs_tunable_set_string(zt, val); + break; + default: + err = EOPNOTSUPP; + break; + } + return (err); +} + +/* The public get function. Delegates to the type-specific version. */ +int +zfs_tunable_get(const zfs_tunable_t *zt, char *val, size_t valsz) +{ + int err; + switch (zt->zt_type) { + case ZFS_TUNABLE_TYPE_INT: + err = zfs_tunable_get_int(zt, val, valsz); + break; + case ZFS_TUNABLE_TYPE_UINT: + err = zfs_tunable_get_uint(zt, val, valsz); + break; + case ZFS_TUNABLE_TYPE_ULONG: + err = zfs_tunable_get_ulong(zt, val, valsz); + break; + case ZFS_TUNABLE_TYPE_U64: + err = zfs_tunable_get_u64(zt, val, valsz); + break; + case ZFS_TUNABLE_TYPE_STRING: + err = zfs_tunable_get_string(zt, val, valsz); + break; + default: + err = EOPNOTSUPP; + break; + } + return (err); +} diff --git a/sys/contrib/openzfs/lib/libuutil/libuutil.abi b/sys/contrib/openzfs/lib/libuutil/libuutil.abi index 0052f0d47a7f..2a740afa07ca 100644 --- a/sys/contrib/openzfs/lib/libuutil/libuutil.abi +++ b/sys/contrib/openzfs/lib/libuutil/libuutil.abi @@ -244,6 +244,10 @@ <elf-symbol name='uu_strerror' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='uu_strndup' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='uu_zalloc' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_tunable_get' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_tunable_iter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_tunable_lookup' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_tunable_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> </elf-function-symbols> <abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'> <typedef-decl name='__pid_t' type-id='95e97e5e' id='3629bad8'/> @@ -978,8 +982,6 @@ </abi-instr> <abi-instr address-size='64' path='lib/libspl/os/linux/gethostid.c' language='LANG_C99'> <type-decl name='long long unsigned int' size-in-bits='64' id='3a47d82b'/> - <pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/> - <qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/> <function-decl name='fclose' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='822cd80b'/> <return type-id='95e97e5e'/> @@ -1307,6 +1309,91 @@ <return type-id='48b5725f'/> </function-decl> </abi-instr> + <abi-instr address-size='64' path='lib/libspl/tunables.c' language='LANG_C99'> + <enum-decl name='zfs_tunable_type_t' naming-typedef-id='f50b1525' id='56905369'> + <underlying-type type-id='9cac1fee'/> + <enumerator name='ZFS_TUNABLE_TYPE_INT' value='0'/> + <enumerator name='ZFS_TUNABLE_TYPE_UINT' value='1'/> + <enumerator name='ZFS_TUNABLE_TYPE_ULONG' value='2'/> + <enumerator name='ZFS_TUNABLE_TYPE_U64' value='3'/> + <enumerator name='ZFS_TUNABLE_TYPE_STRING' value='4'/> + </enum-decl> + <typedef-decl name='zfs_tunable_type_t' type-id='56905369' id='f50b1525'/> + <enum-decl name='zfs_tunable_perm_t' naming-typedef-id='ada7336b' id='e80e6ebf'> + <underlying-type type-id='9cac1fee'/> + <enumerator name='ZFS_TUNABLE_PERM_ZMOD_RW' value='0'/> + <enumerator name='ZFS_TUNABLE_PERM_ZMOD_RD' value='1'/> + </enum-decl> + <typedef-decl name='zfs_tunable_perm_t' type-id='e80e6ebf' id='ada7336b'/> + <class-decl name='zfs_tunable' size-in-bits='320' is-struct='yes' visibility='default' id='1a97ee0e'> + <data-member access='public' layout-offset-in-bits='0'> + <var-decl name='zt_name' type-id='80f4b756' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='64'> + <var-decl name='zt_varp' type-id='eaa32e2f' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='128'> + <var-decl name='zt_varsz' type-id='b59d7dce' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='192'> + <var-decl name='zt_type' type-id='f50b1525' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='224'> + <var-decl name='zt_perm' type-id='ada7336b' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='256'> + <var-decl name='zt_desc' type-id='80f4b756' visibility='default'/> + </data-member> + </class-decl> + <typedef-decl name='zfs_tunable_t' type-id='1a97ee0e' id='12bf5c5e'/> + <typedef-decl name='zfs_tunable_iter_t' type-id='7ef33f92' id='d8d5f4ab'/> + <typedef-decl name='intmax_t' type-id='5b475db0' id='e104d842'/> + <typedef-decl name='uintmax_t' type-id='04d82f4b' id='f8b828c9'/> + <typedef-decl name='__intmax_t' type-id='bd54fe1a' id='5b475db0'/> + <typedef-decl name='__uintmax_t' type-id='7359adad' id='04d82f4b'/> + <pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/> + <qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/> + <qualified-type-def type-id='12bf5c5e' const='yes' id='180e47ee'/> + <pointer-type-def type-id='180e47ee' size-in-bits='64' id='a27af98c'/> + <pointer-type-def type-id='92f86508' size-in-bits='64' id='7ef33f92'/> + <function-decl name='strtoimax' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='9d26089a'/> + <parameter type-id='8c85230f'/> + <parameter type-id='95e97e5e'/> + <return type-id='e104d842'/> + </function-decl> + <function-decl name='strtoumax' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='9d26089a'/> + <parameter type-id='8c85230f'/> + <parameter type-id='95e97e5e'/> + <return type-id='f8b828c9'/> + </function-decl> + <function-decl name='zfs_tunable_lookup' mangled-name='zfs_tunable_lookup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_lookup'> + <parameter type-id='80f4b756' name='name'/> + <return type-id='a27af98c'/> + </function-decl> + <function-decl name='zfs_tunable_iter' mangled-name='zfs_tunable_iter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_iter'> + <parameter type-id='d8d5f4ab' name='cb'/> + <parameter type-id='eaa32e2f' name='arg'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='zfs_tunable_set' mangled-name='zfs_tunable_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_set'> + <parameter type-id='a27af98c' name='zt'/> + <parameter type-id='80f4b756' name='val'/> + <return type-id='95e97e5e'/> + </function-decl> + <function-decl name='zfs_tunable_get' mangled-name='zfs_tunable_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_get'> + <parameter type-id='a27af98c' name='zt'/> + <parameter type-id='26a90f95' name='val'/> + <parameter type-id='b59d7dce' name='valsz'/> + <return type-id='95e97e5e'/> + </function-decl> + <function-type size-in-bits='64' id='92f86508'> + <parameter type-id='a27af98c'/> + <parameter type-id='eaa32e2f'/> + <return type-id='95e97e5e'/> + </function-type> + </abi-instr> <abi-instr address-size='64' path='lib/libuutil/uu_alloc.c' language='LANG_C99'> <type-decl name='char' size-in-bits='8' id='a84c031d'/> <type-decl name='unsigned int' size-in-bits='32' id='f0981eeb'/> diff --git a/sys/contrib/openzfs/lib/libzdb/libzdb.c b/sys/contrib/openzfs/lib/libzdb/libzdb.c index 12144dc65e75..cca1327b1b03 100644 --- a/sys/contrib/openzfs/lib/libzdb/libzdb.c +++ b/sys/contrib/openzfs/lib/libzdb/libzdb.c @@ -93,9 +93,9 @@ livelist_compare(const void *larg, const void *rarg) * Since we're storing blkptrs without cancelling FREE/ALLOC pairs, * it's possible the offsets are equal. In that case, sort by txg */ - if (BP_GET_LOGICAL_BIRTH(l) < BP_GET_LOGICAL_BIRTH(r)) { + if (BP_GET_BIRTH(l) < BP_GET_BIRTH(r)) { return (-1); - } else if (BP_GET_LOGICAL_BIRTH(l) > BP_GET_LOGICAL_BIRTH(r)) { + } else if (BP_GET_BIRTH(l) > BP_GET_BIRTH(r)) { return (+1); } return (0); diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs.abi b/sys/contrib/openzfs/lib/libzfs/libzfs.abi index 35ecdca767db..f988d27a286a 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs.abi +++ b/sys/contrib/openzfs/lib/libzfs/libzfs.abi @@ -451,6 +451,10 @@ <elf-symbol name='zfs_strip_partition' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfs_strip_path' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfs_truncate_shares' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_tunable_get' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_tunable_iter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_tunable_lookup' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_tunable_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfs_type_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfs_unmount' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfs_unmountall' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> @@ -479,6 +483,7 @@ <elf-symbol name='zpool_clear' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_clear_label' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_close' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zpool_collect_leaves' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_collect_unsup_feat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_ddt_prune' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> @@ -528,6 +533,7 @@ <elf-symbol name='zpool_import_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_in_use' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_initialize' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zpool_initialize_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_initialize_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_is_draid_spare' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_iter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> @@ -565,9 +571,11 @@ <elf-symbol name='zpool_props_refresh' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_read_label' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_refresh_stats' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zpool_refresh_stats_from_handle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_reguid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_reopen_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_scan' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zpool_scan_range' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_search_import' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_set_bootenv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_set_guid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> @@ -577,6 +585,7 @@ <elf-symbol name='zpool_state_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_sync_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_trim' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zpool_trim_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_upgrade' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_vdev_attach' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_vdev_clear' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> @@ -631,9 +640,9 @@ <elf-symbol name='fletcher_4_superscalar_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='libzfs_config_ops' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='sa_protocol_names' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='spa_feature_table' size='2464' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='spa_feature_table' size='2632' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfeature_checks_disable' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='zfs_deleg_perm_tab' size='528' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_deleg_perm_tab' size='544' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfs_history_event_names' size='328' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfs_max_dataset_nesting' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfs_userquota_prop_prefixes' size='96' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> @@ -1487,6 +1496,89 @@ <return type-id='48b5725f'/> </function-decl> </abi-instr> + <abi-instr address-size='64' path='lib/libspl/tunables.c' language='LANG_C99'> + <enum-decl name='zfs_tunable_type_t' naming-typedef-id='f50b1525' id='56905369'> + <underlying-type type-id='9cac1fee'/> + <enumerator name='ZFS_TUNABLE_TYPE_INT' value='0'/> + <enumerator name='ZFS_TUNABLE_TYPE_UINT' value='1'/> + <enumerator name='ZFS_TUNABLE_TYPE_ULONG' value='2'/> + <enumerator name='ZFS_TUNABLE_TYPE_U64' value='3'/> + <enumerator name='ZFS_TUNABLE_TYPE_STRING' value='4'/> + </enum-decl> + <typedef-decl name='zfs_tunable_type_t' type-id='56905369' id='f50b1525'/> + <enum-decl name='zfs_tunable_perm_t' naming-typedef-id='ada7336b' id='e80e6ebf'> + <underlying-type type-id='9cac1fee'/> + <enumerator name='ZFS_TUNABLE_PERM_ZMOD_RW' value='0'/> + <enumerator name='ZFS_TUNABLE_PERM_ZMOD_RD' value='1'/> + </enum-decl> + <typedef-decl name='zfs_tunable_perm_t' type-id='e80e6ebf' id='ada7336b'/> + <class-decl name='zfs_tunable' size-in-bits='320' is-struct='yes' visibility='default' id='1a97ee0e'> + <data-member access='public' layout-offset-in-bits='0'> + <var-decl name='zt_name' type-id='80f4b756' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='64'> + <var-decl name='zt_varp' type-id='eaa32e2f' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='128'> + <var-decl name='zt_varsz' type-id='b59d7dce' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='192'> + <var-decl name='zt_type' type-id='f50b1525' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='224'> + <var-decl name='zt_perm' type-id='ada7336b' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='256'> + <var-decl name='zt_desc' type-id='80f4b756' visibility='default'/> + </data-member> + </class-decl> + <typedef-decl name='zfs_tunable_t' type-id='1a97ee0e' id='12bf5c5e'/> + <typedef-decl name='zfs_tunable_iter_t' type-id='7ef33f92' id='d8d5f4ab'/> + <typedef-decl name='intmax_t' type-id='5b475db0' id='e104d842'/> + <typedef-decl name='uintmax_t' type-id='04d82f4b' id='f8b828c9'/> + <typedef-decl name='__intmax_t' type-id='bd54fe1a' id='5b475db0'/> + <typedef-decl name='__uintmax_t' type-id='7359adad' id='04d82f4b'/> + <qualified-type-def type-id='12bf5c5e' const='yes' id='180e47ee'/> + <pointer-type-def type-id='180e47ee' size-in-bits='64' id='a27af98c'/> + <pointer-type-def type-id='92f86508' size-in-bits='64' id='7ef33f92'/> + <function-decl name='strtoimax' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='9d26089a'/> + <parameter type-id='8c85230f'/> + <parameter type-id='95e97e5e'/> + <return type-id='e104d842'/> + </function-decl> + <function-decl name='strtoumax' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='9d26089a'/> + <parameter type-id='8c85230f'/> + <parameter type-id='95e97e5e'/> + <return type-id='f8b828c9'/> + </function-decl> + <function-decl name='zfs_tunable_lookup' mangled-name='zfs_tunable_lookup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_lookup'> + <parameter type-id='80f4b756' name='name'/> + <return type-id='a27af98c'/> + </function-decl> + <function-decl name='zfs_tunable_iter' mangled-name='zfs_tunable_iter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_iter'> + <parameter type-id='d8d5f4ab' name='cb'/> + <parameter type-id='eaa32e2f' name='arg'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='zfs_tunable_set' mangled-name='zfs_tunable_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_set'> + <parameter type-id='a27af98c' name='zt'/> + <parameter type-id='80f4b756' name='val'/> + <return type-id='95e97e5e'/> + </function-decl> + <function-decl name='zfs_tunable_get' mangled-name='zfs_tunable_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_get'> + <parameter type-id='a27af98c' name='zt'/> + <parameter type-id='26a90f95' name='val'/> + <parameter type-id='b59d7dce' name='valsz'/> + <return type-id='95e97e5e'/> + </function-decl> + <function-type size-in-bits='64' id='92f86508'> + <parameter type-id='a27af98c'/> + <parameter type-id='eaa32e2f'/> + <return type-id='95e97e5e'/> + </function-type> + </abi-instr> <abi-instr address-size='64' path='lib/libtpool/thread_pool.c' language='LANG_C99'> <array-type-def dimensions='1' type-id='49ef3ffd' size-in-bits='1024' id='a14403f5'> <subrange length='16' type-id='7359adad' id='848d0938'/> @@ -3000,6 +3092,10 @@ <parameter type-id='dace003f'/> <return type-id='80f4b756'/> </function-decl> + <function-decl name='fnvlist_dup' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='22cce67b'/> + <return type-id='5ce45b60'/> + </function-decl> <function-decl name='fnvpair_value_nvlist' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='3fa542f0'/> <return type-id='5ce45b60'/> @@ -3044,6 +3140,11 @@ <parameter type-id='37e3bd22' name='missing'/> <return type-id='95e97e5e'/> </function-decl> + <function-decl name='zpool_refresh_stats_from_handle' mangled-name='zpool_refresh_stats_from_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_refresh_stats_from_handle'> + <parameter type-id='4c81de99' name='dzhp'/> + <parameter type-id='4c81de99' name='szhp'/> + <return type-id='48b5725f'/> + </function-decl> <function-decl name='zpool_skip_pool' mangled-name='zpool_skip_pool' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_skip_pool'> <parameter type-id='80f4b756' name='poolname'/> <return type-id='c19b74c3'/> @@ -4135,13 +4236,6 @@ <parameter type-id='58603c44'/> <return type-id='9c313c2d'/> </function-decl> - <function-decl name='zpool_prop_get_feature' mangled-name='zpool_prop_get_feature' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_feature'> - <parameter type-id='4c81de99'/> - <parameter type-id='80f4b756'/> - <parameter type-id='26a90f95'/> - <parameter type-id='b59d7dce'/> - <return type-id='95e97e5e'/> - </function-decl> <function-decl name='zfs_iter_snapshots_v2' mangled-name='zfs_iter_snapshots_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapshots_v2'> <parameter type-id='9200a744'/> <parameter type-id='95e97e5e'/> @@ -5930,7 +6024,9 @@ <enumerator name='VDEV_PROP_TRIM_SUPPORT' value='49'/> <enumerator name='VDEV_PROP_TRIM_ERRORS' value='50'/> <enumerator name='VDEV_PROP_SLOW_IOS' value='51'/> - <enumerator name='VDEV_NUM_PROPS' value='52'/> + <enumerator name='VDEV_PROP_SIT_OUT' value='52'/> + <enumerator name='VDEV_PROP_AUTOSIT' value='53'/> + <enumerator name='VDEV_NUM_PROPS' value='54'/> </enum-decl> <typedef-decl name='vdev_prop_t' type-id='1573bec8' id='5aa5c90c'/> <class-decl name='zpool_load_policy' size-in-bits='256' is-struct='yes' visibility='default' id='2f65b36f'> @@ -6210,7 +6306,10 @@ <enumerator name='SPA_FEATURE_FAST_DEDUP' value='41'/> <enumerator name='SPA_FEATURE_LONGNAME' value='42'/> <enumerator name='SPA_FEATURE_LARGE_MICROZAP' value='43'/> - <enumerator name='SPA_FEATURES' value='44'/> + <enumerator name='SPA_FEATURE_DYNAMIC_GANG_HEADER' value='44'/> + <enumerator name='SPA_FEATURE_BLOCK_CLONING_ENDIAN' value='45'/> + <enumerator name='SPA_FEATURE_PHYSICAL_REWRITE' value='46'/> + <enumerator name='SPA_FEATURES' value='47'/> </enum-decl> <typedef-decl name='spa_feature_t' type-id='33ecb627' id='d6618c78'/> <qualified-type-def type-id='80f4b756' const='yes' id='b99c00c9'/> @@ -6629,6 +6728,13 @@ <parameter type-id='e4378506' name='plp'/> <return type-id='95e97e5e'/> </function-decl> + <function-decl name='zpool_prop_get_feature' mangled-name='zpool_prop_get_feature' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_feature'> + <parameter type-id='4c81de99' name='zhp'/> + <parameter type-id='80f4b756' name='propname'/> + <parameter type-id='26a90f95' name='buf'/> + <parameter type-id='b59d7dce' name='len'/> + <return type-id='95e97e5e'/> + </function-decl> <function-decl name='zpool_get_state' mangled-name='zpool_get_state' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_state'> <parameter type-id='4c81de99' name='zhp'/> <return type-id='95e97e5e'/> @@ -6710,6 +6816,11 @@ <parameter type-id='95e97e5e' name='flags'/> <return type-id='95e97e5e'/> </function-decl> + <function-decl name='zpool_initialize_one' mangled-name='zpool_initialize_one' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_initialize_one'> + <parameter type-id='4c81de99' name='zhp'/> + <parameter type-id='eaa32e2f' name='data'/> + <return type-id='95e97e5e'/> + </function-decl> <function-decl name='zpool_initialize' mangled-name='zpool_initialize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_initialize'> <parameter type-id='4c81de99' name='zhp'/> <parameter type-id='7063e1ab' name='cmd_type'/> @@ -6722,6 +6833,17 @@ <parameter type-id='5ce45b60' name='vds'/> <return type-id='95e97e5e'/> </function-decl> + <function-decl name='zpool_collect_leaves' mangled-name='zpool_collect_leaves' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_collect_leaves'> + <parameter type-id='4c81de99' name='zhp'/> + <parameter type-id='5ce45b60' name='nvroot'/> + <parameter type-id='5ce45b60' name='res'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='zpool_trim_one' mangled-name='zpool_trim_one' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_trim_one'> + <parameter type-id='4c81de99' name='zhp'/> + <parameter type-id='eaa32e2f' name='data'/> + <return type-id='95e97e5e'/> + </function-decl> <function-decl name='zpool_trim' mangled-name='zpool_trim' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_trim'> <parameter type-id='4c81de99' name='zhp'/> <parameter type-id='b1146b8d' name='cmd_type'/> @@ -6735,6 +6857,14 @@ <parameter type-id='b51cf3c2' name='cmd'/> <return type-id='95e97e5e'/> </function-decl> + <function-decl name='zpool_scan_range' mangled-name='zpool_scan_range' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_scan_range'> + <parameter type-id='4c81de99' name='zhp'/> + <parameter type-id='7313fbe2' name='func'/> + <parameter type-id='b51cf3c2' name='cmd'/> + <parameter type-id='c9d12d66' name='date_start'/> + <parameter type-id='c9d12d66' name='date_end'/> + <return type-id='95e97e5e'/> + </function-decl> <function-decl name='zpool_find_vdev_by_physpath' mangled-name='zpool_find_vdev_by_physpath' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_find_vdev_by_physpath'> <parameter type-id='4c81de99' name='zhp'/> <parameter type-id='80f4b756' name='ppath'/> @@ -9175,10 +9305,6 @@ <parameter type-id='5ce45b60'/> <return type-id='48b5725f'/> </function-decl> - <function-decl name='fnvlist_dup' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='22cce67b'/> - <return type-id='5ce45b60'/> - </function-decl> <function-decl name='spl_pagesize' mangled-name='spl_pagesize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='spl_pagesize'> <return type-id='b59d7dce'/> </function-decl> @@ -9394,8 +9520,8 @@ </function-decl> </abi-instr> <abi-instr address-size='64' path='module/zcommon/zfeature_common.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='83f29ca2' size-in-bits='19712' id='fd4573e5'> - <subrange length='44' type-id='7359adad' id='cf8ba455'/> + <array-type-def dimensions='1' type-id='83f29ca2' size-in-bits='21056' id='fd43354e'> + <subrange length='47' type-id='7359adad' id='8f8900fe'/> </array-type-def> <enum-decl name='zfeature_flags' id='6db816a4'> <underlying-type type-id='9cac1fee'/> @@ -9403,6 +9529,7 @@ <enumerator name='ZFEATURE_FLAG_MOS' value='2'/> <enumerator name='ZFEATURE_FLAG_ACTIVATE_ON_ENABLE' value='4'/> <enumerator name='ZFEATURE_FLAG_PER_DATASET' value='8'/> + <enumerator name='ZFEATURE_FLAG_NO_UPGRADE' value='16'/> </enum-decl> <typedef-decl name='zfeature_flags_t' type-id='6db816a4' id='fc329033'/> <enum-decl name='zfeature_type' id='c4fa2355'> @@ -9472,7 +9599,7 @@ <pointer-type-def type-id='611586a1' size-in-bits='64' id='2e243169'/> <qualified-type-def type-id='eaa32e2f' const='yes' id='83be723c'/> <pointer-type-def type-id='83be723c' size-in-bits='64' id='7acd98a2'/> - <var-decl name='spa_feature_table' type-id='fd4573e5' mangled-name='spa_feature_table' visibility='default' elf-symbol-id='spa_feature_table'/> + <var-decl name='spa_feature_table' type-id='fd43354e' mangled-name='spa_feature_table' visibility='default' elf-symbol-id='spa_feature_table'/> <var-decl name='zfeature_checks_disable' type-id='c19b74c3' mangled-name='zfeature_checks_disable' visibility='default' elf-symbol-id='zfeature_checks_disable'/> <function-decl name='opendir' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='80f4b756'/> @@ -9550,8 +9677,8 @@ </function-decl> </abi-instr> <abi-instr address-size='64' path='module/zcommon/zfs_deleg.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='fa1870fd' size-in-bits='4224' id='55e705e7'> - <subrange length='33' type-id='7359adad' id='6a5934df'/> + <array-type-def dimensions='1' type-id='fa1870fd' size-in-bits='4352' id='55f84f08'> + <subrange length='34' type-id='7359adad' id='6a6a7e00'/> </array-type-def> <array-type-def dimensions='1' type-id='fa1870fd' size-in-bits='infinite' id='7c00e69d'> <subrange length='infinite' id='031f2035'/> @@ -9581,30 +9708,31 @@ <enumerator name='ZFS_DELEG_NOTE_PROMOTE' value='5'/> <enumerator name='ZFS_DELEG_NOTE_RENAME' value='6'/> <enumerator name='ZFS_DELEG_NOTE_SEND' value='7'/> - <enumerator name='ZFS_DELEG_NOTE_RECEIVE' value='8'/> - <enumerator name='ZFS_DELEG_NOTE_ALLOW' value='9'/> - <enumerator name='ZFS_DELEG_NOTE_USERPROP' value='10'/> - <enumerator name='ZFS_DELEG_NOTE_MOUNT' value='11'/> - <enumerator name='ZFS_DELEG_NOTE_SHARE' value='12'/> - <enumerator name='ZFS_DELEG_NOTE_USERQUOTA' value='13'/> - <enumerator name='ZFS_DELEG_NOTE_GROUPQUOTA' value='14'/> - <enumerator name='ZFS_DELEG_NOTE_USERUSED' value='15'/> - <enumerator name='ZFS_DELEG_NOTE_GROUPUSED' value='16'/> - <enumerator name='ZFS_DELEG_NOTE_USEROBJQUOTA' value='17'/> - <enumerator name='ZFS_DELEG_NOTE_GROUPOBJQUOTA' value='18'/> - <enumerator name='ZFS_DELEG_NOTE_USEROBJUSED' value='19'/> - <enumerator name='ZFS_DELEG_NOTE_GROUPOBJUSED' value='20'/> - <enumerator name='ZFS_DELEG_NOTE_HOLD' value='21'/> - <enumerator name='ZFS_DELEG_NOTE_RELEASE' value='22'/> - <enumerator name='ZFS_DELEG_NOTE_DIFF' value='23'/> - <enumerator name='ZFS_DELEG_NOTE_BOOKMARK' value='24'/> - <enumerator name='ZFS_DELEG_NOTE_LOAD_KEY' value='25'/> - <enumerator name='ZFS_DELEG_NOTE_CHANGE_KEY' value='26'/> - <enumerator name='ZFS_DELEG_NOTE_PROJECTUSED' value='27'/> - <enumerator name='ZFS_DELEG_NOTE_PROJECTQUOTA' value='28'/> - <enumerator name='ZFS_DELEG_NOTE_PROJECTOBJUSED' value='29'/> - <enumerator name='ZFS_DELEG_NOTE_PROJECTOBJQUOTA' value='30'/> - <enumerator name='ZFS_DELEG_NOTE_NONE' value='31'/> + <enumerator name='ZFS_DELEG_NOTE_SEND_RAW' value='8'/> + <enumerator name='ZFS_DELEG_NOTE_RECEIVE' value='9'/> + <enumerator name='ZFS_DELEG_NOTE_ALLOW' value='10'/> + <enumerator name='ZFS_DELEG_NOTE_USERPROP' value='11'/> + <enumerator name='ZFS_DELEG_NOTE_MOUNT' value='12'/> + <enumerator name='ZFS_DELEG_NOTE_SHARE' value='13'/> + <enumerator name='ZFS_DELEG_NOTE_USERQUOTA' value='14'/> + <enumerator name='ZFS_DELEG_NOTE_GROUPQUOTA' value='15'/> + <enumerator name='ZFS_DELEG_NOTE_USERUSED' value='16'/> + <enumerator name='ZFS_DELEG_NOTE_GROUPUSED' value='17'/> + <enumerator name='ZFS_DELEG_NOTE_USEROBJQUOTA' value='18'/> + <enumerator name='ZFS_DELEG_NOTE_GROUPOBJQUOTA' value='19'/> + <enumerator name='ZFS_DELEG_NOTE_USEROBJUSED' value='20'/> + <enumerator name='ZFS_DELEG_NOTE_GROUPOBJUSED' value='21'/> + <enumerator name='ZFS_DELEG_NOTE_HOLD' value='22'/> + <enumerator name='ZFS_DELEG_NOTE_RELEASE' value='23'/> + <enumerator name='ZFS_DELEG_NOTE_DIFF' value='24'/> + <enumerator name='ZFS_DELEG_NOTE_BOOKMARK' value='25'/> + <enumerator name='ZFS_DELEG_NOTE_LOAD_KEY' value='26'/> + <enumerator name='ZFS_DELEG_NOTE_CHANGE_KEY' value='27'/> + <enumerator name='ZFS_DELEG_NOTE_PROJECTUSED' value='28'/> + <enumerator name='ZFS_DELEG_NOTE_PROJECTQUOTA' value='29'/> + <enumerator name='ZFS_DELEG_NOTE_PROJECTOBJUSED' value='30'/> + <enumerator name='ZFS_DELEG_NOTE_PROJECTOBJQUOTA' value='31'/> + <enumerator name='ZFS_DELEG_NOTE_NONE' value='32'/> </enum-decl> <typedef-decl name='zfs_deleg_note_t' type-id='729d4547' id='4613c173'/> <class-decl name='zfs_deleg_perm_tab' size-in-bits='128' is-struct='yes' visibility='default' id='5aa05c1f'> diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_config.c b/sys/contrib/openzfs/lib/libzfs/libzfs_config.c index 0d2102191389..9d704e4303ff 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_config.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_config.c @@ -308,6 +308,23 @@ zpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing) } /* + * Copies the pool config and state from szhp to dzhp. szhp and dzhp must + * represent the same pool. Used by pool_list_refresh() to avoid another + * round-trip into the kernel to get stats already collected earlier in the + * function. + */ +void +zpool_refresh_stats_from_handle(zpool_handle_t *dzhp, zpool_handle_t *szhp) +{ + VERIFY0(strcmp(dzhp->zpool_name, szhp->zpool_name)); + nvlist_free(dzhp->zpool_old_config); + dzhp->zpool_old_config = dzhp->zpool_config; + dzhp->zpool_config = fnvlist_dup(szhp->zpool_config); + dzhp->zpool_config_size = szhp->zpool_config_size; + dzhp->zpool_state = szhp->zpool_state; +} + +/* * The following environment variables are undocumented * and should be used for testing purposes only: * diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_crypto.c b/sys/contrib/openzfs/lib/libzfs/libzfs_crypto.c index 8907802ec259..b34a44c30eb4 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_crypto.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_crypto.c @@ -584,7 +584,7 @@ get_key_material_https(libzfs_handle_t *hdl, const char *uri, goto end; } - int kfd = -1; + int kfd; #ifdef O_TMPFILE kfd = open(getenv("TMPDIR") ?: "/tmp", O_RDWR | O_TMPFILE | O_EXCL | O_CLOEXEC, 0600); diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c b/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c index 91560b40b022..e1b91fc47291 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c @@ -1039,7 +1039,6 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl, nvlist_t *ret; int chosen_normal = -1; int chosen_utf = -1; - int set_maxbs = 0; if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) { (void) no_memory(hdl); @@ -1258,46 +1257,20 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl, (void) zfs_error(hdl, EZFS_BADPROP, errbuf); goto error; } - /* save the ZFS_PROP_RECORDSIZE during create op */ - if (zpool_hdl == NULL && prop == ZFS_PROP_RECORDSIZE) { - set_maxbs = intval; - } break; } case ZFS_PROP_SPECIAL_SMALL_BLOCKS: { - int maxbs = - set_maxbs == 0 ? SPA_OLD_MAXBLOCKSIZE : set_maxbs; + int maxbs = SPA_MAXBLOCKSIZE; char buf[64]; - if (zpool_hdl != NULL) { - char state[64] = ""; - - maxbs = zpool_get_prop_int(zpool_hdl, - ZPOOL_PROP_MAXBLOCKSIZE, NULL); - - /* - * Issue a warning but do not fail so that - * tests for settable properties succeed. - */ - if (zpool_prop_get_feature(zpool_hdl, - "feature@allocation_classes", state, - sizeof (state)) != 0 || - strcmp(state, ZFS_FEATURE_ACTIVE) != 0) { - (void) fprintf(stderr, gettext( - "%s: property requires a special " - "device in the pool\n"), propname); - } - } - if (intval != 0 && - (intval < SPA_MINBLOCKSIZE || - intval > maxbs || !ISP2(intval))) { + if (intval > SPA_MAXBLOCKSIZE) { zfs_nicebytes(maxbs, buf, sizeof (buf)); zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid '%s=%llu' property: must be zero " - "or a power of 2 from 512B to %s"), - propname, (unsigned long long)intval, buf); + "invalid '%s' property: must be between " + "zero and %s"), + propname, buf); (void) zfs_error(hdl, EZFS_BADPROP, errbuf); goto error; } diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c b/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c index 6aa0375f98d7..5f50bce531f7 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c @@ -81,7 +81,7 @@ get_stats_for_obj(differ_info_t *di, const char *dsname, uint64_t obj, /* we can get stats even if we failed to get a path */ (void) memcpy(sb, &zc.zc_stat, sizeof (zfs_stat_t)); if (error == 0) { - ASSERT(di->zerr == 0); + ASSERT0(di->zerr); (void) strlcpy(pn, zc.zc_value, maxlen); return (0); } @@ -404,7 +404,7 @@ write_free_diffs(FILE *fp, differ_info_t *di, dmu_diff_record_t *dr) (void) strlcpy(zc.zc_name, di->fromsnap, sizeof (zc.zc_name)); zc.zc_obj = dr->ddr_first - 1; - ASSERT(di->zerr == 0); + ASSERT0(di->zerr); while (zc.zc_obj < dr->ddr_last) { int err; diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_import.c b/sys/contrib/openzfs/lib/libzfs/libzfs_import.c index 599e8e6f7819..7f276e9592c9 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_import.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_import.c @@ -122,7 +122,7 @@ const pool_config_ops_t libzfs_config_ops = { static uint64_t label_offset(uint64_t size, int l) { - ASSERT(P2PHASE_TYPED(size, sizeof (vdev_label_t), uint64_t) == 0); + ASSERT0(P2PHASE_TYPED(size, sizeof (vdev_label_t), uint64_t)); return (l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ? 0 : size - VDEV_LABELS * sizeof (vdev_label_t))); } diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c b/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c index 2a81b658d342..5c9e2199eed4 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c @@ -516,7 +516,7 @@ zfs_mount_at(zfs_handle_t *zhp, const char *options, int flags, } else if (rc == ENOTSUP) { int spa_version; - VERIFY(zfs_spa_version(zhp, &spa_version) == 0); + VERIFY0(zfs_spa_version(zhp, &spa_version)); zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Can't mount a version %llu " "file system on a version %d pool. Pool must be" diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c b/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c index 6f8fb994f814..ce154ae1a4cd 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c @@ -31,6 +31,7 @@ * Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com> * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> * Copyright (c) 2021, 2023, Klara Inc. + * Copyright (c) 2025 Hewlett Packard Enterprise Development LP. */ #include <errno.h> @@ -896,7 +897,7 @@ int zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval) { zfs_cmd_t zc = {"\0"}; - int ret = -1; + int ret; char errbuf[ERRBUFLEN]; nvlist_t *nvl = NULL; nvlist_t *realprops; @@ -1422,30 +1423,6 @@ zpool_get_state(zpool_handle_t *zhp) } /* - * Check if vdev list contains a special vdev - */ -static boolean_t -zpool_has_special_vdev(nvlist_t *nvroot) -{ - nvlist_t **child; - uint_t children; - - if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, &child, - &children) == 0) { - for (uint_t c = 0; c < children; c++) { - const char *bias; - - if (nvlist_lookup_string(child[c], - ZPOOL_CONFIG_ALLOCATION_BIAS, &bias) == 0 && - strcmp(bias, VDEV_ALLOC_BIAS_SPECIAL) == 0) { - return (B_TRUE); - } - } - } - return (B_FALSE); -} - -/* * Check if vdev list contains a dRAID vdev */ static boolean_t @@ -1548,16 +1525,6 @@ zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, goto create_failed; } - if (nvlist_exists(zc_fsprops, - zfs_prop_to_name(ZFS_PROP_SPECIAL_SMALL_BLOCKS)) && - !zpool_has_special_vdev(nvroot)) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "%s property requires a special vdev"), - zfs_prop_to_name(ZFS_PROP_SPECIAL_SMALL_BLOCKS)); - (void) zfs_error(hdl, EZFS_BADPROP, errbuf); - goto create_failed; - } - if (!zc_props && (nvlist_alloc(&zc_props, NV_UNIQUE_NAME, 0) != 0)) { goto create_failed; @@ -2470,6 +2437,30 @@ xlate_init_err(int err) return (err); } +int +zpool_initialize_one(zpool_handle_t *zhp, void *data) +{ + int error; + libzfs_handle_t *hdl = zpool_get_handle(zhp); + const char *pool_name = zpool_get_name(zhp); + if (zpool_open_silent(hdl, pool_name, &zhp) != 0) + return (-1); + initialize_cbdata_t *cb = data; + nvlist_t *vdevs = fnvlist_alloc(); + + nvlist_t *config = zpool_get_config(zhp, NULL); + nvlist_t *nvroot = fnvlist_lookup_nvlist(config, + ZPOOL_CONFIG_VDEV_TREE); + zpool_collect_leaves(zhp, nvroot, vdevs); + if (cb->wait) + error = zpool_initialize_wait(zhp, cb->cmd_type, vdevs); + else + error = zpool_initialize(zhp, cb->cmd_type, vdevs); + fnvlist_free(vdevs); + + return (error); +} + /* * Begin, suspend, cancel, or uninit (clear) the initialization (initializing * of all free blocks) for the given vdevs in the given pool. @@ -2590,6 +2581,58 @@ xlate_trim_err(int err) return (err); } +void +zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res) +{ + libzfs_handle_t *hdl = zhp->zpool_hdl; + uint_t children = 0; + nvlist_t **child; + uint_t i; + + (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, + &child, &children); + + if (children == 0) { + char *path = zpool_vdev_name(hdl, zhp, nvroot, + VDEV_NAME_PATH); + + if (strcmp(path, VDEV_TYPE_INDIRECT) != 0 && + strcmp(path, VDEV_TYPE_HOLE) != 0) + fnvlist_add_boolean(res, path); + + free(path); + return; + } + + for (i = 0; i < children; i++) { + zpool_collect_leaves(zhp, child[i], res); + } +} + +int +zpool_trim_one(zpool_handle_t *zhp, void *data) +{ + int error; + libzfs_handle_t *hdl = zpool_get_handle(zhp); + const char *pool_name = zpool_get_name(zhp); + if (zpool_open_silent(hdl, pool_name, &zhp) != 0) + return (-1); + + trim_cbdata_t *cb = data; + nvlist_t *vdevs = fnvlist_alloc(); + + /* no individual leaf vdevs specified, so add them all */ + nvlist_t *config = zpool_get_config(zhp, NULL); + nvlist_t *nvroot = fnvlist_lookup_nvlist(config, + ZPOOL_CONFIG_VDEV_TREE); + + zpool_collect_leaves(zhp, nvroot, vdevs); + error = zpool_trim(zhp, cb->cmd_type, vdevs, &cb->trim_flags); + fnvlist_free(vdevs); + + return (error); +} + static int zpool_trim_wait(zpool_handle_t *zhp, nvlist_t *vdev_guids) { @@ -2730,7 +2773,13 @@ out: * Scan the pool. */ int -zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd) +zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd) { + return (zpool_scan_range(zhp, func, cmd, 0, 0)); +} + +int +zpool_scan_range(zpool_handle_t *zhp, pool_scan_func_t func, + pool_scrub_cmd_t cmd, time_t date_start, time_t date_end) { char errbuf[ERRBUFLEN]; int err; @@ -2739,6 +2788,8 @@ zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd) nvlist_t *args = fnvlist_alloc(); fnvlist_add_uint64(args, "scan_type", (uint64_t)func); fnvlist_add_uint64(args, "scan_command", (uint64_t)cmd); + fnvlist_add_uint64(args, "scan_date_start", (uint64_t)date_start); + fnvlist_add_uint64(args, "scan_date_end", (uint64_t)date_end); err = lzc_scrub(ZFS_IOC_POOL_SCRUB, zhp->zpool_name, args, NULL); fnvlist_free(args); @@ -4344,7 +4395,7 @@ zpool_set_guid(zpool_handle_t *zhp, const uint64_t *guid) libzfs_handle_t *hdl = zhp->zpool_hdl; nvlist_t *nvl = NULL; zfs_cmd_t zc = {"\0"}; - int error = -1; + int error; if (guid != NULL) { if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) @@ -5127,9 +5178,10 @@ zpool_load_compat(const char *compat, boolean_t *features, char *report, /* special cases (unset), "" and "off" => enable all features */ if (compat == NULL || compat[0] == '\0' || strcmp(compat, ZPOOL_COMPAT_OFF) == 0) { - if (features != NULL) + if (features != NULL) { for (uint_t i = 0; i < SPA_FEATURES; i++) features[i] = B_TRUE; + } if (report != NULL) strlcpy(report, gettext("all features enabled"), rlen); return (ZPOOL_COMPATIBILITY_OK); @@ -5497,6 +5549,8 @@ zpool_get_vdev_prop_value(nvlist_t *nvprop, vdev_prop_t prop, char *prop_name, /* Only use if provided by the RAIDZ VDEV above */ if (prop == VDEV_PROP_RAIDZ_EXPANDING) return (ENOENT); + if (prop == VDEV_PROP_SIT_OUT) + return (ENOENT); } if (vdev_prop_index_to_string(prop, intval, (const char **)&strval) != 0) @@ -5666,8 +5720,16 @@ zpool_set_vdev_prop(zpool_handle_t *zhp, const char *vdevname, nvlist_free(nvl); nvlist_free(outnvl); - if (ret) - (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf); + if (ret) { + if (errno == ENOTSUP) { + zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN, + "property not supported for this vdev")); + (void) zfs_error(zhp->zpool_hdl, EZFS_PROPTYPE, errbuf); + } else { + (void) zpool_standard_error(zhp->zpool_hdl, errno, + errbuf); + } + } return (ret); } diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c b/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c index 1ad10ebb3c15..77134d197904 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c @@ -2505,7 +2505,7 @@ zfs_send_cb_impl(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, err = ENOENT; if (sdd.cleanup_fd != -1) { - VERIFY(0 == close(sdd.cleanup_fd)); + VERIFY0(close(sdd.cleanup_fd)); sdd.cleanup_fd = -1; } @@ -2531,7 +2531,7 @@ err_out: fnvlist_free(sdd.snapholds); if (sdd.cleanup_fd != -1) - VERIFY(0 == close(sdd.cleanup_fd)); + VERIFY0(close(sdd.cleanup_fd)); return (err); } @@ -5108,7 +5108,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, nvlist_t *holds, *errors = NULL; int cleanup_fd = -1; - VERIFY(0 == nvlist_alloc(&holds, 0, KM_SLEEP)); + VERIFY0(nvlist_alloc(&holds, 0, KM_SLEEP)); for (pair = nvlist_next_nvpair(snapholds_nvlist, NULL); pair != NULL; pair = nvlist_next_nvpair(snapholds_nvlist, pair)) { @@ -5560,7 +5560,7 @@ zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, if ((cp = strchr(nonpackage_sendfs, '@')) != NULL) *cp = '\0'; sendfs = nonpackage_sendfs; - VERIFY(finalsnap == NULL); + VERIFY0P(finalsnap); } return (zfs_receive_one(hdl, infd, tosnap, originsnap, flags, &drr, &drr_noswap, sendfs, stream_nv, stream_avl, top_zfs, diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_status.c b/sys/contrib/openzfs/lib/libzfs/libzfs_status.c index 1ee703968237..a589ca6896f0 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_status.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_status.c @@ -98,57 +98,57 @@ static const char *const zfs_msgid_table[] = { #define NMSGID (sizeof (zfs_msgid_table) / sizeof (zfs_msgid_table[0])) static int -vdev_missing(vdev_stat_t *vs, uint_t vsc) +vdev_missing(vdev_stat_t *vs, uint_t vsc, void *arg) { - (void) vsc; + (void) vsc, (void) arg; return (vs->vs_state == VDEV_STATE_CANT_OPEN && vs->vs_aux == VDEV_AUX_OPEN_FAILED); } static int -vdev_faulted(vdev_stat_t *vs, uint_t vsc) +vdev_faulted(vdev_stat_t *vs, uint_t vsc, void *arg) { - (void) vsc; + (void) vsc, (void) arg; return (vs->vs_state == VDEV_STATE_FAULTED); } static int -vdev_errors(vdev_stat_t *vs, uint_t vsc) +vdev_errors(vdev_stat_t *vs, uint_t vsc, void *arg) { - (void) vsc; + (void) vsc, (void) arg; return (vs->vs_state == VDEV_STATE_DEGRADED || vs->vs_read_errors != 0 || vs->vs_write_errors != 0 || vs->vs_checksum_errors != 0); } static int -vdev_broken(vdev_stat_t *vs, uint_t vsc) +vdev_broken(vdev_stat_t *vs, uint_t vsc, void *arg) { - (void) vsc; + (void) vsc, (void) arg; return (vs->vs_state == VDEV_STATE_CANT_OPEN); } static int -vdev_offlined(vdev_stat_t *vs, uint_t vsc) +vdev_offlined(vdev_stat_t *vs, uint_t vsc, void *arg) { - (void) vsc; + (void) vsc, (void) arg; return (vs->vs_state == VDEV_STATE_OFFLINE); } static int -vdev_removed(vdev_stat_t *vs, uint_t vsc) +vdev_removed(vdev_stat_t *vs, uint_t vsc, void *arg) { - (void) vsc; + (void) vsc, (void) arg; return (vs->vs_state == VDEV_STATE_REMOVED); } static int -vdev_non_native_ashift(vdev_stat_t *vs, uint_t vsc) +vdev_non_native_ashift(vdev_stat_t *vs, uint_t vsc, void *arg) { - if (getenv("ZPOOL_STATUS_NON_NATIVE_ASHIFT_IGNORE") != NULL) - return (0); + uint64_t ashift = *(uint64_t *)arg; return (VDEV_STAT_VALID(vs_physical_ashift, vsc) && + (ashift == 0 || vs->vs_configured_ashift < ashift) && vs->vs_configured_ashift < vs->vs_physical_ashift); } @@ -156,8 +156,8 @@ vdev_non_native_ashift(vdev_stat_t *vs, uint_t vsc) * Detect if any leaf devices that have seen errors or could not be opened. */ static boolean_t -find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t), - boolean_t ignore_replacing) +find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t, void *), + void *arg, boolean_t ignore_replacing) { nvlist_t **child; uint_t c, children; @@ -177,14 +177,16 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t), if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_CHILDREN, &child, &children) == 0) { - for (c = 0; c < children; c++) - if (find_vdev_problem(child[c], func, ignore_replacing)) + for (c = 0; c < children; c++) { + if (find_vdev_problem(child[c], func, arg, + ignore_replacing)) return (B_TRUE); + } } else { uint_t vsc; vdev_stat_t *vs = (vdev_stat_t *)fnvlist_lookup_uint64_array( vdev, ZPOOL_CONFIG_VDEV_STATS, &vsc); - if (func(vs, vsc) != 0) + if (func(vs, vsc, arg) != 0) return (B_TRUE); } @@ -193,9 +195,11 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t), */ if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_L2CACHE, &child, &children) == 0) { - for (c = 0; c < children; c++) - if (find_vdev_problem(child[c], func, ignore_replacing)) + for (c = 0; c < children; c++) { + if (find_vdev_problem(child[c], func, arg, + ignore_replacing)) return (B_TRUE); + } } return (B_FALSE); @@ -220,7 +224,7 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t), */ static zpool_status_t check_status(nvlist_t *config, boolean_t isimport, - zpool_errata_t *erratap, const char *compat) + zpool_errata_t *erratap, const char *compat, uint64_t ashift) { pool_scan_stat_t *ps = NULL; uint_t vsc, psc; @@ -371,15 +375,15 @@ check_status(nvlist_t *config, boolean_t isimport, * Bad devices in non-replicated config. */ if (vs->vs_state == VDEV_STATE_CANT_OPEN && - find_vdev_problem(nvroot, vdev_faulted, B_TRUE)) + find_vdev_problem(nvroot, vdev_faulted, NULL, B_TRUE)) return (ZPOOL_STATUS_FAULTED_DEV_NR); if (vs->vs_state == VDEV_STATE_CANT_OPEN && - find_vdev_problem(nvroot, vdev_missing, B_TRUE)) + find_vdev_problem(nvroot, vdev_missing, NULL, B_TRUE)) return (ZPOOL_STATUS_MISSING_DEV_NR); if (vs->vs_state == VDEV_STATE_CANT_OPEN && - find_vdev_problem(nvroot, vdev_broken, B_TRUE)) + find_vdev_problem(nvroot, vdev_broken, NULL, B_TRUE)) return (ZPOOL_STATUS_CORRUPT_LABEL_NR); /* @@ -402,35 +406,37 @@ check_status(nvlist_t *config, boolean_t isimport, /* * Missing devices in a replicated config. */ - if (find_vdev_problem(nvroot, vdev_faulted, B_TRUE)) + if (find_vdev_problem(nvroot, vdev_faulted, NULL, B_TRUE)) return (ZPOOL_STATUS_FAULTED_DEV_R); - if (find_vdev_problem(nvroot, vdev_missing, B_TRUE)) + if (find_vdev_problem(nvroot, vdev_missing, NULL, B_TRUE)) return (ZPOOL_STATUS_MISSING_DEV_R); - if (find_vdev_problem(nvroot, vdev_broken, B_TRUE)) + if (find_vdev_problem(nvroot, vdev_broken, NULL, B_TRUE)) return (ZPOOL_STATUS_CORRUPT_LABEL_R); /* * Devices with errors */ - if (!isimport && find_vdev_problem(nvroot, vdev_errors, B_TRUE)) + if (!isimport && find_vdev_problem(nvroot, vdev_errors, NULL, B_TRUE)) return (ZPOOL_STATUS_FAILING_DEV); /* * Offlined devices */ - if (find_vdev_problem(nvroot, vdev_offlined, B_TRUE)) + if (find_vdev_problem(nvroot, vdev_offlined, NULL, B_TRUE)) return (ZPOOL_STATUS_OFFLINE_DEV); /* * Removed device */ - if (find_vdev_problem(nvroot, vdev_removed, B_TRUE)) + if (find_vdev_problem(nvroot, vdev_removed, NULL, B_TRUE)) return (ZPOOL_STATUS_REMOVED_DEV); /* * Suboptimal, but usable, ashift configuration. */ - if (find_vdev_problem(nvroot, vdev_non_native_ashift, B_FALSE)) + if (!isimport && + getenv("ZPOOL_STATUS_NON_NATIVE_ASHIFT_IGNORE") == NULL && + find_vdev_problem(nvroot, vdev_non_native_ashift, &ashift, B_FALSE)) return (ZPOOL_STATUS_NON_NATIVE_ASHIFT); /* @@ -484,7 +490,8 @@ check_status(nvlist_t *config, boolean_t isimport, } for (i = 0; i < SPA_FEATURES; i++) { zfeature_info_t *fi = &spa_feature_table[i]; - if (!fi->fi_zfs_mod_supported) + if (!fi->fi_zfs_mod_supported || + (fi->fi_flags & ZFEATURE_FLAG_NO_UPGRADE)) continue; if (c_features[i] && !nvlist_exists(feat, fi->fi_guid)) return (ZPOOL_STATUS_FEAT_DISABLED); @@ -509,8 +516,10 @@ zpool_get_status(zpool_handle_t *zhp, const char **msgid, ZFS_MAXPROPLEN, NULL, B_FALSE) != 0) compatibility[0] = '\0'; + uint64_t ashift = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, NULL); + zpool_status_t ret = check_status(zhp->zpool_config, B_FALSE, errata, - compatibility); + compatibility, ashift); if (msgid != NULL) { if (ret >= NMSGID) @@ -525,7 +534,7 @@ zpool_status_t zpool_import_status(nvlist_t *config, const char **msgid, zpool_errata_t *errata) { - zpool_status_t ret = check_status(config, B_TRUE, errata, NULL); + zpool_status_t ret = check_status(config, B_TRUE, errata, NULL, 0); if (ret >= NMSGID) *msgid = NULL; diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_util.c b/sys/contrib/openzfs/lib/libzfs/libzfs_util.c index 4edddc2a759b..26f5135dff62 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_util.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_util.c @@ -776,6 +776,11 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) case ZFS_ERR_ASHIFT_MISMATCH: zfs_verror(hdl, EZFS_ASHIFT_MISMATCH, fmt, ap); break; + case ZFS_ERR_TOO_MANY_SITOUTS: + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "too many disks " + "already sitting out")); + zfs_verror(hdl, EZFS_BUSY, fmt, ap); + break; default: zfs_error_aux(hdl, "%s", zfs_strerror(error)); zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); diff --git a/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi b/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi index 63904f447e85..263cad045f7a 100644 --- a/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi +++ b/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi @@ -222,6 +222,10 @@ <elf-symbol name='spl_pagesize' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='strlcat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='strlcpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_tunable_get' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_tunable_iter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_tunable_lookup' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_tunable_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> </elf-function-symbols> <abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'> <class-decl name='__va_list_tag' size-in-bits='192' is-struct='yes' visibility='default' id='d5027220'> @@ -974,8 +978,6 @@ </abi-instr> <abi-instr address-size='64' path='lib/libspl/os/linux/gethostid.c' language='LANG_C99'> <type-decl name='long long unsigned int' size-in-bits='64' id='3a47d82b'/> - <pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/> - <qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/> <function-decl name='strtoull' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='9d26089a'/> <parameter type-id='8c85230f'/> @@ -1107,11 +1109,6 @@ <parameter type-id='822cd80b'/> <return type-id='95e97e5e'/> </function-decl> - <function-decl name='strcmp' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='80f4b756'/> - <parameter type-id='80f4b756'/> - <return type-id='95e97e5e'/> - </function-decl> <function-decl name='strerror' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='95e97e5e'/> <return type-id='26a90f95'/> @@ -1258,6 +1255,96 @@ <return type-id='48b5725f'/> </function-decl> </abi-instr> + <abi-instr address-size='64' path='lib/libspl/tunables.c' language='LANG_C99'> + <enum-decl name='zfs_tunable_type_t' naming-typedef-id='f50b1525' id='56905369'> + <underlying-type type-id='9cac1fee'/> + <enumerator name='ZFS_TUNABLE_TYPE_INT' value='0'/> + <enumerator name='ZFS_TUNABLE_TYPE_UINT' value='1'/> + <enumerator name='ZFS_TUNABLE_TYPE_ULONG' value='2'/> + <enumerator name='ZFS_TUNABLE_TYPE_U64' value='3'/> + <enumerator name='ZFS_TUNABLE_TYPE_STRING' value='4'/> + </enum-decl> + <typedef-decl name='zfs_tunable_type_t' type-id='56905369' id='f50b1525'/> + <enum-decl name='zfs_tunable_perm_t' naming-typedef-id='ada7336b' id='e80e6ebf'> + <underlying-type type-id='9cac1fee'/> + <enumerator name='ZFS_TUNABLE_PERM_ZMOD_RW' value='0'/> + <enumerator name='ZFS_TUNABLE_PERM_ZMOD_RD' value='1'/> + </enum-decl> + <typedef-decl name='zfs_tunable_perm_t' type-id='e80e6ebf' id='ada7336b'/> + <class-decl name='zfs_tunable' size-in-bits='320' is-struct='yes' visibility='default' id='1a97ee0e'> + <data-member access='public' layout-offset-in-bits='0'> + <var-decl name='zt_name' type-id='80f4b756' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='64'> + <var-decl name='zt_varp' type-id='eaa32e2f' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='128'> + <var-decl name='zt_varsz' type-id='b59d7dce' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='192'> + <var-decl name='zt_type' type-id='f50b1525' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='224'> + <var-decl name='zt_perm' type-id='ada7336b' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='256'> + <var-decl name='zt_desc' type-id='80f4b756' visibility='default'/> + </data-member> + </class-decl> + <typedef-decl name='zfs_tunable_t' type-id='1a97ee0e' id='12bf5c5e'/> + <typedef-decl name='zfs_tunable_iter_t' type-id='7ef33f92' id='d8d5f4ab'/> + <typedef-decl name='intmax_t' type-id='5b475db0' id='e104d842'/> + <typedef-decl name='uintmax_t' type-id='04d82f4b' id='f8b828c9'/> + <typedef-decl name='__intmax_t' type-id='bd54fe1a' id='5b475db0'/> + <typedef-decl name='__uintmax_t' type-id='7359adad' id='04d82f4b'/> + <pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/> + <qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/> + <qualified-type-def type-id='12bf5c5e' const='yes' id='180e47ee'/> + <pointer-type-def type-id='180e47ee' size-in-bits='64' id='a27af98c'/> + <pointer-type-def type-id='92f86508' size-in-bits='64' id='7ef33f92'/> + <function-decl name='strtoimax' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='9d26089a'/> + <parameter type-id='8c85230f'/> + <parameter type-id='95e97e5e'/> + <return type-id='e104d842'/> + </function-decl> + <function-decl name='strtoumax' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='9d26089a'/> + <parameter type-id='8c85230f'/> + <parameter type-id='95e97e5e'/> + <return type-id='f8b828c9'/> + </function-decl> + <function-decl name='strcmp' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='80f4b756'/> + <parameter type-id='80f4b756'/> + <return type-id='95e97e5e'/> + </function-decl> + <function-decl name='zfs_tunable_lookup' mangled-name='zfs_tunable_lookup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_lookup'> + <parameter type-id='80f4b756' name='name'/> + <return type-id='a27af98c'/> + </function-decl> + <function-decl name='zfs_tunable_iter' mangled-name='zfs_tunable_iter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_iter'> + <parameter type-id='d8d5f4ab' name='cb'/> + <parameter type-id='eaa32e2f' name='arg'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='zfs_tunable_set' mangled-name='zfs_tunable_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_set'> + <parameter type-id='a27af98c' name='zt'/> + <parameter type-id='80f4b756' name='val'/> + <return type-id='95e97e5e'/> + </function-decl> + <function-decl name='zfs_tunable_get' mangled-name='zfs_tunable_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_get'> + <parameter type-id='a27af98c' name='zt'/> + <parameter type-id='26a90f95' name='val'/> + <parameter type-id='b59d7dce' name='valsz'/> + <return type-id='95e97e5e'/> + </function-decl> + <function-type size-in-bits='64' id='92f86508'> + <parameter type-id='a27af98c'/> + <parameter type-id='eaa32e2f'/> + <return type-id='95e97e5e'/> + </function-type> + </abi-instr> <abi-instr address-size='64' path='lib/libzfs_core/libzfs_core.c' language='LANG_C99'> <array-type-def dimensions='1' type-id='03085adc' size-in-bits='192' id='083f8d58'> <subrange length='3' type-id='7359adad' id='56f209d2'/> diff --git a/sys/contrib/openzfs/lib/libzpool/Makefile.am b/sys/contrib/openzfs/lib/libzpool/Makefile.am index 8553b377a760..aeacc595b363 100644 --- a/sys/contrib/openzfs/lib/libzpool/Makefile.am +++ b/sys/contrib/openzfs/lib/libzpool/Makefile.am @@ -177,6 +177,7 @@ nodist_libzpool_la_SOURCES = \ module/zfs/zfs_byteswap.c \ module/zfs/zfs_chksum.c \ module/zfs/zfs_debug_common.c \ + module/zfs/zfs_crrd.c \ module/zfs/zfs_fm.c \ module/zfs/zfs_fuid.c \ module/zfs/zfs_ratelimit.c \ @@ -199,7 +200,7 @@ libzpool_la_LIBADD = \ libzstd.la \ libzutil.la -libzpool_la_LIBADD += $(LIBCLOCK_GETTIME) $(ZLIB_LIBS) -ldl -lm +libzpool_la_LIBADD += $(LIBCLOCK_GETTIME) $(ZLIB_LIBS) -lm libzpool_la_LDFLAGS = -pthread diff --git a/sys/contrib/openzfs/lib/libzpool/abd_os.c b/sys/contrib/openzfs/lib/libzpool/abd_os.c index 0d5795de143a..8bd7a64ab24a 100644 --- a/sys/contrib/openzfs/lib/libzpool/abd_os.c +++ b/sys/contrib/openzfs/lib/libzpool/abd_os.c @@ -302,7 +302,7 @@ abd_iter_at_end(struct abd_iter *aiter) void abd_iter_advance(struct abd_iter *aiter, size_t amount) { - ASSERT3P(aiter->iter_mapaddr, ==, NULL); + ASSERT0P(aiter->iter_mapaddr); ASSERT0(aiter->iter_mapsize); if (abd_iter_at_end(aiter)) @@ -315,7 +315,7 @@ abd_iter_advance(struct abd_iter *aiter, size_t amount) void abd_iter_map(struct abd_iter *aiter) { - ASSERT3P(aiter->iter_mapaddr, ==, NULL); + ASSERT0P(aiter->iter_mapaddr); ASSERT0(aiter->iter_mapsize); if (abd_iter_at_end(aiter)) diff --git a/sys/contrib/openzfs/lib/libzpool/kernel.c b/sys/contrib/openzfs/lib/libzpool/kernel.c index e397fc851cc1..70eba5099119 100644 --- a/sys/contrib/openzfs/lib/libzpool/kernel.c +++ b/sys/contrib/openzfs/lib/libzpool/kernel.c @@ -23,6 +23,7 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2018 by Delphix. All rights reserved. * Copyright (c) 2016 Actifio, Inc. All rights reserved. + * Copyright (c) 2025, Klara, Inc. */ #include <assert.h> @@ -38,6 +39,7 @@ #include <sys/processor.h> #include <sys/rrwlock.h> #include <sys/spa.h> +#include <sys/spa_impl.h> #include <sys/stat.h> #include <sys/systeminfo.h> #include <sys/time.h> @@ -369,7 +371,7 @@ cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) if (delta <= 0) return (-1); - VERIFY(gettimeofday(&tv, NULL) == 0); + VERIFY0(gettimeofday(&tv, NULL)); ts.tv_sec = tv.tv_sec + delta / hz; ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC + (delta % hz) * (NANOSEC / hz); @@ -644,39 +646,60 @@ __dprintf(boolean_t dprint, const char *file, const char *func, * cmn_err() and panic() * ========================================================================= */ -static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; -static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; -__attribute__((noreturn)) void -vpanic(const char *fmt, va_list adx) +static __attribute__((noreturn)) void +panic_stop_or_abort(void) { - (void) fprintf(stderr, "error: "); - (void) vfprintf(stderr, fmt, adx); - (void) fprintf(stderr, "\n"); + const char *stopenv = getenv("LIBZPOOL_PANIC_STOP"); + if (stopenv != NULL && atoi(stopenv)) { + fputs("libzpool: LIBZPOOL_PANIC_STOP is set, sending " + "SIGSTOP to process group\n", stderr); + fflush(stderr); + + kill(0, SIGSTOP); + + fputs("libzpool: continued after panic stop, " + "aborting\n", stderr); + } abort(); /* think of it as a "user-level crash dump" */ } -__attribute__((noreturn)) void -panic(const char *fmt, ...) -{ - va_list adx; +static void +vcmn_msg(int ce, const char *fmt, va_list adx) +{ + switch (ce) { + case CE_IGNORE: + return; + case CE_CONT: + break; + case CE_NOTE: + fputs("libzpool: NOTICE: ", stderr); + break; + case CE_WARN: + fputs("libzpool: WARNING: ", stderr); + break; + case CE_PANIC: + fputs("libzpool: PANIC: ", stderr); + break; + default: + fputs("libzpool: [unknown severity %d]: ", stderr); + break; + } - va_start(adx, fmt); - vpanic(fmt, adx); - va_end(adx); + vfprintf(stderr, fmt, adx); + if (ce != CE_CONT) + fputc('\n', stderr); + fflush(stderr); } void vcmn_err(int ce, const char *fmt, va_list adx) { + vcmn_msg(ce, fmt, adx); + if (ce == CE_PANIC) - vpanic(fmt, adx); - if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ - (void) fprintf(stderr, "%s", ce_prefix[ce]); - (void) vfprintf(stderr, fmt, adx); - (void) fprintf(stderr, "%s", ce_suffix[ce]); - } + panic_stop_or_abort(); } void @@ -689,6 +712,25 @@ cmn_err(int ce, const char *fmt, ...) va_end(adx); } +__attribute__((noreturn)) void +panic(const char *fmt, ...) +{ + va_list adx; + + va_start(adx, fmt); + vcmn_msg(CE_PANIC, fmt, adx); + va_end(adx); + + panic_stop_or_abort(); +} + +__attribute__((noreturn)) void +vpanic(const char *fmt, va_list adx) +{ + vcmn_msg(CE_PANIC, fmt, adx); + panic_stop_or_abort(); +} + /* * ========================================================================= * misc routines @@ -811,6 +853,79 @@ umem_out_of_memory(void) return (0); } +static void +spa_config_load(void) +{ + void *buf = NULL; + nvlist_t *nvlist, *child; + nvpair_t *nvpair; + char *pathname; + zfs_file_t *fp; + zfs_file_attr_t zfa; + uint64_t fsize; + int err; + + /* + * Open the configuration file. + */ + pathname = kmem_alloc(MAXPATHLEN, KM_SLEEP); + + (void) snprintf(pathname, MAXPATHLEN, "%s", spa_config_path); + + err = zfs_file_open(pathname, O_RDONLY, 0, &fp); + if (err) + err = zfs_file_open(ZPOOL_CACHE_BOOT, O_RDONLY, 0, &fp); + + kmem_free(pathname, MAXPATHLEN); + + if (err) + return; + + if (zfs_file_getattr(fp, &zfa)) + goto out; + + fsize = zfa.zfa_size; + buf = kmem_alloc(fsize, KM_SLEEP); + + /* + * Read the nvlist from the file. + */ + if (zfs_file_read(fp, buf, fsize, NULL) < 0) + goto out; + + /* + * Unpack the nvlist. + */ + if (nvlist_unpack(buf, fsize, &nvlist, KM_SLEEP) != 0) + goto out; + + /* + * Iterate over all elements in the nvlist, creating a new spa_t for + * each one with the specified configuration. + */ + mutex_enter(&spa_namespace_lock); + nvpair = NULL; + while ((nvpair = nvlist_next_nvpair(nvlist, nvpair)) != NULL) { + if (nvpair_type(nvpair) != DATA_TYPE_NVLIST) + continue; + + child = fnvpair_value_nvlist(nvpair); + + if (spa_lookup(nvpair_name(nvpair)) != NULL) + continue; + (void) spa_add(nvpair_name(nvpair), child, NULL); + } + mutex_exit(&spa_namespace_lock); + + nvlist_free(nvlist); + +out: + if (buf != NULL) + kmem_free(buf, fsize); + + zfs_file_close(fp); +} + void kernel_init(int mode) { @@ -835,6 +950,7 @@ kernel_init(int mode) zstd_init(); spa_init((spa_mode_t)mode); + spa_config_load(); fletcher_4_init(); @@ -1025,25 +1141,13 @@ spl_fstrans_unmark(fstrans_cookie_t cookie) } int -__spl_pf_fstrans_check(void) -{ - return (0); -} - -int kmem_cache_reap_active(void) { return (0); } void -zvol_create_minor(const char *name) -{ - (void) name; -} - -void -zvol_create_minors_recursive(const char *name) +zvol_create_minors(const char *name) { (void) name; } @@ -1073,8 +1177,8 @@ zvol_rename_minors(spa_t *spa, const char *oldname, const char *newname, int zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fpp) { - int fd = -1; - int dump_fd = -1; + int fd; + int dump_fd; int err; int old_umask = 0; zfs_file_t *fp; @@ -1175,7 +1279,7 @@ zfs_file_write(zfs_file_t *fp, const void *buf, size_t count, ssize_t *resid) */ int zfs_file_pwrite(zfs_file_t *fp, const void *buf, - size_t count, loff_t pos, ssize_t *resid) + size_t count, loff_t pos, uint8_t ashift, ssize_t *resid) { ssize_t rc, split, done; int sectors; @@ -1185,8 +1289,8 @@ zfs_file_pwrite(zfs_file_t *fp, const void *buf, * system calls so that the process can be killed in between. * This is used by ztest to simulate realistic failure modes. */ - sectors = count >> SPA_MINBLOCKSHIFT; - split = (sectors > 0 ? rand() % sectors : 0) << SPA_MINBLOCKSHIFT; + sectors = count >> ashift; + split = (sectors > 0 ? rand() % sectors : 0) << ashift; rc = pwrite64(fp->f_fd, buf, split, pos); if (rc != -1) { done = rc; diff --git a/sys/contrib/openzfs/lib/libzpool/util.c b/sys/contrib/openzfs/lib/libzpool/util.c index a297daedbd4d..66d6f43967d5 100644 --- a/sys/contrib/openzfs/lib/libzpool/util.c +++ b/sys/contrib/openzfs/lib/libzpool/util.c @@ -36,7 +36,7 @@ #include <sys/fs/zfs.h> #include <sys/zfs_refcount.h> #include <sys/zfs_ioctl.h> -#include <dlfcn.h> +#include <sys/tunables.h> #include <libzutil.h> /* @@ -137,12 +137,10 @@ show_pool_stats(spa_t *spa) nvlist_t *config, *nvroot; const char *name; - VERIFY(spa_get_stats(spa_name(spa), &config, NULL, 0) == 0); + VERIFY0(spa_get_stats(spa_name(spa), &config, NULL, 0)); - VERIFY(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, - &nvroot) == 0); - VERIFY(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, - &name) == 0); + VERIFY0(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot)); + VERIFY0(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, &name)); show_vdev_stats(name, ZPOOL_CONFIG_CHILDREN, nvroot, 0); show_vdev_stats(NULL, ZPOOL_CONFIG_L2CACHE, nvroot, 0); @@ -151,97 +149,119 @@ show_pool_stats(spa_t *spa) nvlist_free(config); } -/* *k_out must be freed by the caller */ +/* + * Common helper for working with libzpool tunables from the command line. + * + * Valid inputs: + * + * <name> show named tunable and value + * <name>=<value> set tunable value + * + * show show all tunables and values + * show=<name> show named tunable and value + * info show info about all tunables + * info=<name> show info about named tunable + */ + +typedef enum { SHOW, INFO, SET } tunable_mode_t; + static int -set_global_var_parse_kv(const char *arg, char **k_out, u_longlong_t *v_out) +list_tunables_cb(const zfs_tunable_t *tunable, void *arg) { - int err; - VERIFY(arg); - char *d = strdup(arg); - - char *save = NULL; - char *k = strtok_r(d, "=", &save); - char *v_str = strtok_r(NULL, "=", &save); - char *follow = strtok_r(NULL, "=", &save); - if (k == NULL || v_str == NULL || follow != NULL) { - err = EINVAL; - goto err_free; - } - - u_longlong_t val = strtoull(v_str, NULL, 0); - if (val > UINT32_MAX) { - fprintf(stderr, "Value for global variable '%s' must " - "be a 32-bit unsigned integer, got '%s'\n", k, v_str); - err = EOVERFLOW; - goto err_free; + const tunable_mode_t *mode = arg; + + static const char *type[] = { + "int", "uint", "ulong", "u64", "str", + }; + static const char *perm[] = { + "rw", "rd", + }; + + if (*mode == SHOW) { + char val[64]; + int err = zfs_tunable_get(tunable, val, sizeof (val)); + if (err == 0) + printf("%s: %s\n", tunable->zt_name, val); + else + printf("%s: [error getting tunable value: %s]\n", + tunable->zt_name, strerror(err)); + } else { + printf("%s [%s %s]: %s\n", tunable->zt_name, + type[tunable->zt_type], perm[tunable->zt_perm], + tunable->zt_desc); } - *k_out = strdup(k); - *v_out = val; - free(d); return (0); - -err_free: - free(d); - - return (err); } - -/* - * Sets given global variable in libzpool to given unsigned 32-bit value. - * arg: "<variable>=<value>" - */ int -set_global_var(char const *arg) +handle_tunable_option(const char *_arg, boolean_t quiet) { - void *zpoolhdl; - char *varname; - u_longlong_t val; - int ret; - -#ifndef _ZFS_LITTLE_ENDIAN - /* - * On big endian systems changing a 64-bit variable would set the high - * 32 bits instead of the low 32 bits, which could cause unexpected - * results. - */ - fprintf(stderr, "Setting global variables is only supported on " - "little-endian systems\n"); - ret = ENOTSUP; - goto out_ret; -#endif + int err = 0; + char *arg = strdup(_arg); + char *k, *v; + + v = arg; + k = strsep(&v, "="); + + tunable_mode_t mode; + + if (strcmp(k, "show") == 0) { + mode = SHOW; + k = v; + } else if (strcmp(k, "info") == 0) { + mode = INFO; + k = v; + } else if (v == NULL) { + mode = SHOW; + } else { + mode = SET; + } - if ((ret = set_global_var_parse_kv(arg, &varname, &val)) != 0) { - goto out_ret; + if (quiet && mode != SET) { + err = EINVAL; + goto out; } - zpoolhdl = dlopen("libzpool.so", RTLD_LAZY); - if (zpoolhdl != NULL) { - uint32_t *var; - var = dlsym(zpoolhdl, varname); - if (var == NULL) { - fprintf(stderr, "Global variable '%s' does not exist " - "in libzpool.so\n", varname); - ret = EINVAL; - goto out_dlclose; + if (mode == SET) { + const zfs_tunable_t *tunable = zfs_tunable_lookup(k); + if (tunable == NULL) { + err = ENOENT; + goto out; } - *var = (uint32_t)val; + char vold[256], vnew[256]; + if (zfs_tunable_get(tunable, vold, sizeof (vold)) != 0) + strcpy(vold, "???"); + err = zfs_tunable_set(tunable, v); + if (err != 0) + goto out; + if (zfs_tunable_get(tunable, vnew, sizeof (vnew)) != 0) + strcpy(vnew, "???"); + + if (!quiet) + printf("%s: %s -> %s\n", k, vold, vnew); + } else if (k != NULL) { + const zfs_tunable_t *tunable = zfs_tunable_lookup(k); + if (tunable == NULL) { + err = ENOENT; + goto out; + } + list_tunables_cb(tunable, &mode); } else { - fprintf(stderr, "Failed to open libzpool.so to set global " - "variable\n"); - ret = EIO; - goto out_free; + zfs_tunable_iter(list_tunables_cb, &mode); } - ret = 0; +out: + if (!quiet) { + if (err == ENOENT) + fprintf(stderr, "no such tunable: %s\n", k); + else if (err != 0) + fprintf(stderr, "couldn't set tunable '%s': %s\n", + k, strerror(err)); + } -out_dlclose: - dlclose(zpoolhdl); -out_free: - free(varname); -out_ret: - return (ret); + free(arg); + return (err); } static nvlist_t * diff --git a/sys/contrib/openzfs/lib/libzutil/zutil_import.c b/sys/contrib/openzfs/lib/libzutil/zutil_import.c index ccdc874076c3..08367f4c064d 100644 --- a/sys/contrib/openzfs/lib/libzutil/zutil_import.c +++ b/sys/contrib/openzfs/lib/libzutil/zutil_import.c @@ -917,7 +917,7 @@ error: static uint64_t label_offset(uint64_t size, int l) { - ASSERT(P2PHASE_TYPED(size, sizeof (vdev_label_t), uint64_t) == 0); + ASSERT0(P2PHASE_TYPED(size, sizeof (vdev_label_t), uint64_t)); return (l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ? 0 : size - VDEV_LABELS * sizeof (vdev_label_t))); } @@ -1769,7 +1769,7 @@ zpool_find_import_cached(libpc_handle_t *hdl, importargs_t *iarg) fnvlist_add_nvlist(pools, nvpair_name(pair), fnvpair_value_nvlist(pair)); - VERIFY3P(nvlist_next_nvpair(nv, pair), ==, NULL); + VERIFY0P(nvlist_next_nvpair(nv, pair)); iarg->guid = saved_guid; iarg->poolname = saved_poolname; @@ -1903,30 +1903,43 @@ zpool_find_config(libpc_handle_t *hdl, const char *target, nvlist_t **configp, *sepp = '\0'; pools = zpool_search_import(hdl, args); + if (pools == NULL) { + zutil_error_aux(hdl, dgettext(TEXT_DOMAIN, "no pools found")); + (void) zutil_error_fmt(hdl, LPC_UNKNOWN, dgettext(TEXT_DOMAIN, + "failed to find config for pool '%s'"), targetdup); + free(targetdup); + return (ENOENT); + } - if (pools != NULL) { - nvpair_t *elem = NULL; - while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { - VERIFY0(nvpair_value_nvlist(elem, &config)); - if (pool_match(config, targetdup)) { - count++; - if (match != NULL) { - /* multiple matches found */ - continue; - } else { - match = fnvlist_dup(config); - } + nvpair_t *elem = NULL; + while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { + VERIFY0(nvpair_value_nvlist(elem, &config)); + if (pool_match(config, targetdup)) { + count++; + if (match != NULL) { + /* multiple matches found */ + continue; + } else { + match = fnvlist_dup(config); } } - fnvlist_free(pools); } + fnvlist_free(pools); if (count == 0) { + zutil_error_aux(hdl, dgettext(TEXT_DOMAIN, + "no matching pools")); + (void) zutil_error_fmt(hdl, LPC_UNKNOWN, dgettext(TEXT_DOMAIN, + "failed to find config for pool '%s'"), targetdup); free(targetdup); return (ENOENT); } if (count > 1) { + zutil_error_aux(hdl, dgettext(TEXT_DOMAIN, + "more than one matching pool")); + (void) zutil_error_fmt(hdl, LPC_UNKNOWN, dgettext(TEXT_DOMAIN, + "failed to find config for pool '%s'"), targetdup); free(targetdup); fnvlist_free(match); return (EINVAL); |
