From owner-dev-commits-src-all@freebsd.org Sat Mar 13 17:33:02 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id AFEC957D708 for ; Sat, 13 Mar 2021 17:33:02 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4DyVBk4gFpz57DS; Sat, 13 Mar 2021 17:33:02 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 92E636A55; Sat, 13 Mar 2021 17:33:02 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 12DHX2D2055086; Sat, 13 Mar 2021 17:33:02 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 12DHX2l5055084; Sat, 13 Mar 2021 17:33:02 GMT (envelope-from git) Date: Sat, 13 Mar 2021 17:33:02 GMT Message-Id: <202103131733.12DHX2l5055084@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org From: Martin Matuska Subject: git: 9162a1ce3ae9 - vendor/openzfs - Update vendor/openzfs to master-9305ff2ed MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mm X-Git-Repository: src X-Git-Refname: refs/heads/vendor/openzfs X-Git-Reftype: branch X-Git-Commit: 9162a1ce3ae9158ae75ab1835e30ac14d3b6899c Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 13 Mar 2021 17:33:02 -0000 The branch vendor/openzfs has been updated by mm: URL: https://cgit.FreeBSD.org/src/commit/?id=9162a1ce3ae9158ae75ab1835e30ac14d3b6899c commit 9162a1ce3ae9158ae75ab1835e30ac14d3b6899c Author: Martin Matuska AuthorDate: 2021-03-13 17:30:04 +0000 Commit: Martin Matuska CommitDate: 2021-03-13 17:30:04 +0000 Update vendor/openzfs to master-9305ff2ed Notable upstream pull request merges: #11153 Scalable teardown lock for FreeBSD #11651 Don't bomb out when using keylocation=file:// #11667 zvol: call zil_replaying() during replay #11683 abd_get_offset_struct() may allocate new abd #11693 Intentionally allow ZFS_READONLY in zfs_write #11716 zpool import cachefile improvements #11720 FreeBSD: Clean up zfsdev_close to match Linux #11730 FreeBSD: bring back possibility to rewind the checkpoint from bootloader --- .github/workflows/checkstyle.yaml | 2 +- cmd/vdev_id/vdev_id | 9 +- cmd/zpool/zpool_main.c | 307 +++++++++++++-------- cmd/zstream/zstream_redup.c | 1 + config/zfs-build.m4 | 36 +++ configure.ac | 1 + include/os/freebsd/spl/sys/Makefile.am | 3 + include/os/freebsd/spl/sys/debug.h | 80 +++--- include/os/freebsd/zfs/sys/zfs_vfsops_os.h | 118 ++++++-- include/os/freebsd/zfs/sys/zfs_znode_impl.h | 10 +- include/os/linux/spl/sys/debug.h | 78 +++--- include/os/linux/zfs/sys/zfs_vfsops_os.h | 33 +++ include/os/linux/zfs/sys/zfs_znode_impl.h | 10 +- include/sys/dmu_redact.h | 2 + include/sys/zfs_ioctl.h | 1 - lib/libzfs/libzfs_crypto.c | 10 +- lib/libzfs/libzfs_mount.c | 25 +- lib/libzfs/os/freebsd/libzfs_zmount.c | 5 +- lib/libzfs/os/linux/libzfs_mount_os.c | 6 +- lib/libzutil/zutil_import.c | 177 +++++++++--- man/man8/zfs-receive.8 | 10 + man/man8/zfs-send.8 | 7 +- module/Makefile.in | 5 + module/os/freebsd/zfs/kmod_core.c | 18 +- module/os/freebsd/zfs/zfs_dir.c | 5 +- module/os/freebsd/zfs/zfs_vfsops.c | 65 +++-- module/os/freebsd/zfs/zfs_vnops_os.c | 61 +--- module/os/freebsd/zfs/zfs_znode.c | 2 +- module/os/freebsd/zfs/zvol_os.c | 9 +- module/os/linux/zfs/zfs_acl.c | 26 +- module/os/linux/zfs/zfs_vfsops.c | 18 +- module/os/linux/zfs/zio_crypt.c | 1 + module/os/linux/zfs/zvol_os.c | 102 +++++-- module/zcommon/zfs_prop.c | 2 +- module/zfs/abd.c | 6 +- module/zfs/spa_misc.c | 4 +- module/zfs/zfs_ioctl.c | 10 +- module/zfs/zfs_vnops.c | 6 +- module/zfs/zvol.c | 15 +- tests/runfiles/common.run | 1 + tests/zfs-tests/include/commands.cfg | 2 +- tests/zfs-tests/include/libtest.shlib | 19 +- tests/zfs-tests/include/tunables.cfg | 8 +- .../functional/cli_root/zpool/zpool_002_pos.ksh | 37 ++- .../functional/cli_root/zpool/zpool_003_pos.ksh | 39 ++- .../functional/cli_root/zpool_import/Makefile.am | 1 + .../import_cachefile_paths_changed.ksh | 117 ++++++++ .../tests/functional/events/events_002_pos.ksh | 7 +- .../tests/functional/xattr/xattr_003_neg.ksh | 44 +-- 49 files changed, 1063 insertions(+), 498 deletions(-) diff --git a/.github/workflows/checkstyle.yaml b/.github/workflows/checkstyle.yaml index 1707f5bb21db..8dcd5047a748 100644 --- a/.github/workflows/checkstyle.yaml +++ b/.github/workflows/checkstyle.yaml @@ -6,7 +6,7 @@ on: jobs: checkstyle: - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 with: diff --git a/cmd/vdev_id/vdev_id b/cmd/vdev_id/vdev_id index 8a379a72690e..d8918da1078c 100755 --- a/cmd/vdev_id/vdev_id +++ b/cmd/vdev_id/vdev_id @@ -298,8 +298,15 @@ sas_handler() { # Utilize DM device name to gather subordinate block devices # using sysfs to avoid userspace utilities - DMDEV=$(ls -l --full-time /dev/mapper | grep $DM_NAME | + + # If our DEVNAME is something like /dev/dm-177, then we may be + # able to get our DMDEV from it. + DMDEV=$(echo $DEVNAME | sed 's;/dev/;;g') + if [ ! -e /sys/block/$DMDEV/slaves/* ] ; then + # It's not there, try looking in /dev/mapper + DMDEV=$(ls -l --full-time /dev/mapper | grep $DM_NAME | awk '{gsub("../", " "); print $NF}') + fi # Use sysfs pointers in /sys/block/dm-X/slaves because using # userspace tools creates lots of overhead and should be avoided diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index e89eb3bea770..e23604b3d81c 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -2623,8 +2623,8 @@ print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv, /* * Display the status for the given pool. */ -static void -show_import(nvlist_t *config) +static int +show_import(nvlist_t *config, boolean_t report_error) { uint64_t pool_state; vdev_stat_t *vs; @@ -2656,6 +2656,13 @@ show_import(nvlist_t *config) reason = zpool_import_status(config, &msgid, &errata); + /* + * If we're importing using a cachefile, then we won't report any + * errors unless we are in the scan phase of the import. + */ + if (reason != ZPOOL_STATUS_OK && !report_error) + return (reason); + (void) printf(gettext(" pool: %s\n"), name); (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); (void) printf(gettext(" state: %s"), health); @@ -2983,6 +2990,7 @@ show_import(nvlist_t *config) "be part of this pool, though their\n\texact " "configuration cannot be determined.\n")); } + return (0); } static boolean_t @@ -3121,6 +3129,121 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts, return (ret); } +static int +import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags, + char *orig_name, char *new_name, + boolean_t do_destroyed, boolean_t pool_specified, boolean_t do_all, + importargs_t *import) +{ + nvlist_t *config = NULL; + nvlist_t *found_config = NULL; + uint64_t pool_state; + + /* + * At this point we have a list of import candidate configs. Even if + * we were searching by pool name or guid, we still need to + * post-process the list to deal with pool state and possible + * duplicate names. + */ + int err = 0; + nvpair_t *elem = NULL; + boolean_t first = B_TRUE; + while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { + + verify(nvpair_value_nvlist(elem, &config) == 0); + + verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, + &pool_state) == 0); + if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) + continue; + if (do_destroyed && pool_state != POOL_STATE_DESTROYED) + continue; + + verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY, + import->policy) == 0); + + if (!pool_specified) { + if (first) + first = B_FALSE; + else if (!do_all) + (void) printf("\n"); + + if (do_all) { + err |= do_import(config, NULL, mntopts, + props, flags); + } else { + /* + * If we're importing from cachefile, then + * we don't want to report errors until we + * are in the scan phase of the import. If + * we get an error, then we return that error + * to invoke the scan phase. + */ + if (import->cachefile && !import->scan) + err = show_import(config, B_FALSE); + else + (void) show_import(config, B_TRUE); + } + } else if (import->poolname != NULL) { + char *name; + + /* + * We are searching for a pool based on name. + */ + verify(nvlist_lookup_string(config, + ZPOOL_CONFIG_POOL_NAME, &name) == 0); + + if (strcmp(name, import->poolname) == 0) { + if (found_config != NULL) { + (void) fprintf(stderr, gettext( + "cannot import '%s': more than " + "one matching pool\n"), + import->poolname); + (void) fprintf(stderr, gettext( + "import by numeric ID instead\n")); + err = B_TRUE; + } + found_config = config; + } + } else { + uint64_t guid; + + /* + * Search for a pool by guid. + */ + verify(nvlist_lookup_uint64(config, + ZPOOL_CONFIG_POOL_GUID, &guid) == 0); + + if (guid == import->guid) + found_config = config; + } + } + + /* + * If we were searching for a specific pool, verify that we found a + * pool, and then do the import. + */ + if (pool_specified && err == 0) { + if (found_config == NULL) { + (void) fprintf(stderr, gettext("cannot import '%s': " + "no such pool available\n"), orig_name); + err = B_TRUE; + } else { + err |= do_import(found_config, new_name, + mntopts, props, flags); + } + } + + /* + * If we were just looking for pools, report an error if none were + * found. + */ + if (!pool_specified && first) + (void) fprintf(stderr, + gettext("no pools available to import\n")); + return (err); +} + typedef struct target_exists_args { const char *poolname; uint64_t poolguid; @@ -3248,51 +3371,54 @@ zpool_do_checkpoint(int argc, char **argv) /* * zpool import [-d dir] [-D] * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l] - * [-d dir | -c cachefile] [-f] -a + * [-d dir | -c cachefile | -s] [-f] -a * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l] - * [-d dir | -c cachefile] [-f] [-n] [-F] [newpool] + * [-d dir | -c cachefile | -s] [-f] [-n] [-F] + * [newpool] * - * -c Read pool information from a cachefile instead of searching - * devices. + * -c Read pool information from a cachefile instead of searching + * devices. If importing from a cachefile config fails, then + * fallback to searching for devices only in the directories that + * exist in the cachefile. * - * -d Scan in a specific directory, other than /dev/. More than + * -d Scan in a specific directory, other than /dev/. More than * one directory can be specified using multiple '-d' options. * - * -D Scan for previously destroyed pools or import all or only - * specified destroyed pools. + * -D Scan for previously destroyed pools or import all or only + * specified destroyed pools. * - * -R Temporarily import the pool, with all mountpoints relative to + * -R Temporarily import the pool, with all mountpoints relative to * the given root. The pool will remain exported when the machine * is rebooted. * - * -V Import even in the presence of faulted vdevs. This is an - * intentionally undocumented option for testing purposes, and - * treats the pool configuration as complete, leaving any bad + * -V Import even in the presence of faulted vdevs. This is an + * intentionally undocumented option for testing purposes, and + * treats the pool configuration as complete, leaving any bad * vdevs in the FAULTED state. In other words, it does verbatim * import. * - * -f Force import, even if it appears that the pool is active. + * -f Force import, even if it appears that the pool is active. * - * -F Attempt rewind if necessary. + * -F Attempt rewind if necessary. * - * -n See if rewind would work, but don't actually rewind. + * -n See if rewind would work, but don't actually rewind. * - * -N Import the pool but don't mount datasets. + * -N Import the pool but don't mount datasets. * - * -T Specify a starting txg to use for import. This option is - * intentionally undocumented option for testing purposes. + * -T Specify a starting txg to use for import. This option is + * intentionally undocumented option for testing purposes. * - * -a Import all pools found. + * -a Import all pools found. * - * -l Load encryption keys while importing. + * -l Load encryption keys while importing. * - * -o Set property=value and/or temporary mount options (without '='). + * -o Set property=value and/or temporary mount options (without '='). * - * -s Scan using the default search path, the libblkid cache will - * not be consulted. + * -s Scan using the default search path, the libblkid cache will + * not be consulted. * - * --rewind-to-checkpoint - * Import the pool and revert back to the checkpoint. + * --rewind-to-checkpoint + * Import the pool and revert back to the checkpoint. * * The import command scans for pools to import, and import pools based on pool * name and GUID. The pool can also be renamed as part of the import process. @@ -3309,15 +3435,11 @@ zpool_do_import(int argc, char **argv) boolean_t do_all = B_FALSE; boolean_t do_destroyed = B_FALSE; char *mntopts = NULL; - nvpair_t *elem; - nvlist_t *config; uint64_t searchguid = 0; char *searchname = NULL; char *propval; - nvlist_t *found_config; nvlist_t *policy = NULL; nvlist_t *props = NULL; - boolean_t first; int flags = ZFS_IMPORT_NORMAL; uint32_t rewind_policy = ZPOOL_NO_REWIND; boolean_t dryrun = B_FALSE; @@ -3325,7 +3447,8 @@ zpool_do_import(int argc, char **argv) boolean_t xtreme_rewind = B_FALSE; boolean_t do_scan = B_FALSE; boolean_t pool_exists = B_FALSE; - uint64_t pool_state, txg = -1ULL; + boolean_t pool_specified = B_FALSE; + uint64_t txg = -1ULL; char *cachefile = NULL; importargs_t idata = { 0 }; char *endptr; @@ -3447,6 +3570,11 @@ zpool_do_import(int argc, char **argv) usage(B_FALSE); } + if (cachefile && do_scan) { + (void) fprintf(stderr, gettext("-c is incompatible with -s\n")); + usage(B_FALSE); + } + if ((flags & ZFS_IMPORT_LOAD_KEYS) && (flags & ZFS_IMPORT_ONLY)) { (void) fprintf(stderr, gettext("-l is incompatible with -N\n")); usage(B_FALSE); @@ -3527,7 +3655,7 @@ zpool_do_import(int argc, char **argv) searchname = argv[0]; searchguid = 0; } - found_config = NULL; + pool_specified = B_TRUE; /* * User specified a name or guid. Ensure it's unique. @@ -3606,98 +3734,33 @@ zpool_do_import(int argc, char **argv) return (1); } + err = import_pools(pools, props, mntopts, flags, argv[0], + argc == 1 ? NULL : argv[1], do_destroyed, pool_specified, + do_all, &idata); + /* - * At this point we have a list of import candidate configs. Even if - * we were searching by pool name or guid, we still need to - * post-process the list to deal with pool state and possible - * duplicate names. + * If we're using the cachefile and we failed to import, then + * fallback to scanning the directory for pools that match + * those in the cachefile. */ - err = 0; - elem = NULL; - first = B_TRUE; - while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { - - verify(nvpair_value_nvlist(elem, &config) == 0); - - verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, - &pool_state) == 0); - if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) - continue; - if (do_destroyed && pool_state != POOL_STATE_DESTROYED) - continue; - - verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY, - policy) == 0); - - if (argc == 0) { - if (first) - first = B_FALSE; - else if (!do_all) - (void) printf("\n"); - - if (do_all) { - err |= do_import(config, NULL, mntopts, - props, flags); - } else { - show_import(config); - } - } else if (searchname != NULL) { - char *name; - - /* - * We are searching for a pool based on name. - */ - verify(nvlist_lookup_string(config, - ZPOOL_CONFIG_POOL_NAME, &name) == 0); + if (err != 0 && cachefile != NULL) { + (void) printf(gettext("cachefile import failed, retrying\n")); - if (strcmp(name, searchname) == 0) { - if (found_config != NULL) { - (void) fprintf(stderr, gettext( - "cannot import '%s': more than " - "one matching pool\n"), searchname); - (void) fprintf(stderr, gettext( - "import by numeric ID instead\n")); - err = B_TRUE; - } - found_config = config; - } - } else { - uint64_t guid; - - /* - * Search for a pool by guid. - */ - verify(nvlist_lookup_uint64(config, - ZPOOL_CONFIG_POOL_GUID, &guid) == 0); - - if (guid == searchguid) - found_config = config; - } - } + /* + * We use the scan flag to gather the directories that exist + * in the cachefile. If we need to fallback to searching for + * the pool config, we will only search devices in these + * directories. + */ + idata.scan = B_TRUE; + nvlist_free(pools); + pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops); - /* - * If we were searching for a specific pool, verify that we found a - * pool, and then do the import. - */ - if (argc != 0 && err == 0) { - if (found_config == NULL) { - (void) fprintf(stderr, gettext("cannot import '%s': " - "no such pool available\n"), argv[0]); - err = B_TRUE; - } else { - err |= do_import(found_config, argc == 1 ? NULL : - argv[1], mntopts, props, flags); - } + err = import_pools(pools, props, mntopts, flags, argv[0], + argc == 1 ? NULL : argv[1], do_destroyed, pool_specified, + do_all, &idata); } - /* - * If we were just looking for pools, report an error if none were - * found. - */ - if (argc == 0 && first) - (void) fprintf(stderr, - gettext("no pools available to import\n")); - error: nvlist_free(props); nvlist_free(pools); @@ -7785,8 +7848,8 @@ print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs) * do not print estimated time if hours_left is more than * 30 days */ - (void) printf(gettext(" %s copied out of %s at %s/s, " - "%.2f%% done"), + (void) printf(gettext( + "\t%s copied out of %s at %s/s, %.2f%% done"), examined_buf, total_buf, rate_buf, 100 * fraction_done); if (hours_left < (30 * 24)) { (void) printf(gettext(", %lluh%um to go\n"), @@ -7801,8 +7864,8 @@ print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs) if (prs->prs_mapping_memory > 0) { char mem_buf[7]; zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf)); - (void) printf(gettext(" %s memory used for " - "removed device mappings\n"), + (void) printf(gettext( + "\t%s memory used for removed device mappings\n"), mem_buf); } } diff --git a/cmd/zstream/zstream_redup.c b/cmd/zstream/zstream_redup.c index 41f1068e3dfc..15dd8a1ed126 100644 --- a/cmd/zstream/zstream_redup.c +++ b/cmd/zstream/zstream_redup.c @@ -248,6 +248,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose) fflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo); fflags &= ~(DMU_BACKUP_FEATURE_DEDUP | DMU_BACKUP_FEATURE_DEDUPPROPS); + /* cppcheck-suppress syntaxError */ DMU_SET_FEATUREFLAGS(drrb->drr_versioninfo, fflags); int sz = drr->drr_payloadlen; diff --git a/config/zfs-build.m4 b/config/zfs-build.m4 index 305d0c6936b2..cd5996c0424c 100644 --- a/config/zfs-build.m4 +++ b/config/zfs-build.m4 @@ -11,6 +11,7 @@ AC_DEFUN([ZFS_AC_DEBUG_ENABLE], [ DEBUG_CPPFLAGS="-DDEBUG -UNDEBUG" DEBUG_LDFLAGS="" DEBUG_ZFS="_with_debug" + WITH_DEBUG="true" AC_DEFINE(ZFS_DEBUG, 1, [zfs debugging enabled]) KERNEL_DEBUG_CFLAGS="-Werror" @@ -22,6 +23,7 @@ AC_DEFUN([ZFS_AC_DEBUG_DISABLE], [ DEBUG_CPPFLAGS="-UDEBUG -DNDEBUG" DEBUG_LDFLAGS="" DEBUG_ZFS="_without_debug" + WITH_DEBUG="" KERNEL_DEBUG_CFLAGS="" KERNEL_DEBUG_CPPFLAGS="-UDEBUG -DNDEBUG" @@ -51,6 +53,7 @@ AC_DEFUN([ZFS_AC_DEBUG], [ AC_SUBST(DEBUG_CPPFLAGS) AC_SUBST(DEBUG_LDFLAGS) AC_SUBST(DEBUG_ZFS) + AC_SUBST(WITH_DEBUG) AC_SUBST(KERNEL_DEBUG_CFLAGS) AC_SUBST(KERNEL_DEBUG_CPPFLAGS) @@ -152,6 +155,39 @@ AC_DEFUN([ZFS_AC_DEBUG_KMEM_TRACKING], [ AC_MSG_RESULT([$enable_debug_kmem_tracking]) ]) +AC_DEFUN([ZFS_AC_DEBUG_INVARIANTS_DETECT_FREEBSD], [ + AS_IF([sysctl -n kern.conftxt | fgrep -qx $'options\tINVARIANTS'], + [enable_invariants="yes"], + [enable_invariants="no"]) +]) + +AC_DEFUN([ZFS_AC_DEBUG_INVARIANTS_DETECT], [ + AM_COND_IF([BUILD_FREEBSD], + [ZFS_AC_DEBUG_INVARIANTS_DETECT_FREEBSD], + [enable_invariants="no"]) +]) + +dnl # +dnl # Detected for the running kernel by default, enables INVARIANTS features +dnl # in the FreeBSD kernel module. This feature must be used when building +dnl # for a FreeBSD kernel with "options INVARIANTS" in the KERNCONF and must +dnl # not be used when the INVARIANTS option is absent. +dnl # +AC_DEFUN([ZFS_AC_DEBUG_INVARIANTS], [ + AC_MSG_CHECKING([whether FreeBSD kernel INVARIANTS checks are enabled]) + AC_ARG_ENABLE([invariants], + [AS_HELP_STRING([--enable-invariants], + [Enable FreeBSD kernel INVARIANTS checks [[default: detect]]])], + [], [ZFS_AC_DEBUG_INVARIANTS_DETECT]) + + AS_IF([test "x$enable_invariants" = xyes], + [WITH_INVARIANTS="true"], + [WITH_INVARIANTS=""]) + AC_SUBST(WITH_INVARIANTS) + + AC_MSG_RESULT([$enable_invariants]) +]) + AC_DEFUN([ZFS_AC_CONFIG_ALWAYS], [ AX_COUNT_CPUS([]) AC_SUBST(CPU_COUNT) diff --git a/configure.ac b/configure.ac index b2d88554ed7d..07f590b390bd 100644 --- a/configure.ac +++ b/configure.ac @@ -61,6 +61,7 @@ ZFS_AC_DEBUG ZFS_AC_DEBUGINFO ZFS_AC_DEBUG_KMEM ZFS_AC_DEBUG_KMEM_TRACKING +ZFS_AC_DEBUG_INVARIANTS AC_CONFIG_FILES([ Makefile diff --git a/include/os/freebsd/spl/sys/Makefile.am b/include/os/freebsd/spl/sys/Makefile.am index ca45b42b6b8d..6bee47830d9c 100644 --- a/include/os/freebsd/spl/sys/Makefile.am +++ b/include/os/freebsd/spl/sys/Makefile.am @@ -4,6 +4,7 @@ KERNEL_H = \ atomic.h \ byteorder.h \ callb.h \ + ccompat.h \ ccompile.h \ cmn_err.h \ condvar.h \ @@ -18,9 +19,11 @@ KERNEL_H = \ fcntl.h \ file.h \ freebsd_rwlock.h \ + idmap.h \ inttypes.h \ isa_defs.h \ kmem_cache.h \ + kidmap.h \ kmem.h \ kstat.h \ list_impl.h \ diff --git a/include/os/freebsd/spl/sys/debug.h b/include/os/freebsd/spl/sys/debug.h index 2751f57801f7..1f820bc3345f 100644 --- a/include/os/freebsd/spl/sys/debug.h +++ b/include/os/freebsd/spl/sys/debug.h @@ -68,65 +68,65 @@ void spl_dumpstack(void); #define PANIC(fmt, a...) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, fmt, ## a) -#define VERIFY(cond) \ - (void) (unlikely(!(cond)) && \ +#define VERIFY(cond) \ + (void) (unlikely(!(cond)) && \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "%s", "VERIFY(" #cond ") failed\n")) -#define VERIFY3B(LEFT, OP, RIGHT) do { \ - boolean_t _verify3_left = (boolean_t)(LEFT); \ - boolean_t _verify3_right = (boolean_t)(RIGHT); \ - if (!(_verify3_left OP _verify3_right)) \ +#define VERIFY3B(LEFT, OP, RIGHT) do { \ + const boolean_t _verify3_left = (boolean_t)(LEFT); \ + const boolean_t _verify3_right = (boolean_t)(RIGHT);\ + if (unlikely(!(_verify3_left OP _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ - "failed (%d " #OP " %d)\n", \ - (boolean_t) (_verify3_left), \ - (boolean_t) (_verify3_right)); \ + "failed (%d " #OP " %d)\n", \ + (boolean_t) (_verify3_left), \ + (boolean_t) (_verify3_right)); \ } while (0) -#define VERIFY3S(LEFT, OP, RIGHT) do { \ - int64_t _verify3_left = (int64_t)(LEFT); \ - int64_t _verify3_right = (int64_t)(RIGHT); \ - if (!(_verify3_left OP _verify3_right)) \ +#define VERIFY3S(LEFT, OP, RIGHT) do { \ + const int64_t _verify3_left = (int64_t)(LEFT); \ + const int64_t _verify3_right = (int64_t)(RIGHT); \ + if (unlikely(!(_verify3_left OP _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ - "failed (%lld " #OP " %lld)\n", \ - (long long) (_verify3_left), \ - (long long) (_verify3_right)); \ + "failed (%lld " #OP " %lld)\n", \ + (long long) (_verify3_left), \ + (long long) (_verify3_right)); \ } while (0) -#define VERIFY3U(LEFT, OP, RIGHT) do { \ - uint64_t _verify3_left = (uint64_t)(LEFT); \ - uint64_t _verify3_right = (uint64_t)(RIGHT); \ - if (!(_verify3_left OP _verify3_right)) \ +#define VERIFY3U(LEFT, OP, RIGHT) do { \ + const uint64_t _verify3_left = (uint64_t)(LEFT); \ + const uint64_t _verify3_right = (uint64_t)(RIGHT); \ + if (unlikely(!(_verify3_left OP _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ - "failed (%llu " #OP " %llu)\n", \ - (unsigned long long) (_verify3_left), \ - (unsigned long long) (_verify3_right)); \ + "failed (%llu " #OP " %llu)\n", \ + (unsigned long long) (_verify3_left), \ + (unsigned long long) (_verify3_right)); \ } while (0) -#define VERIFY3P(LEFT, OP, RIGHT) do { \ - uintptr_t _verify3_left = (uintptr_t)(LEFT); \ - uintptr_t _verify3_right = (uintptr_t)(RIGHT); \ - if (!(_verify3_left OP _verify3_right)) \ +#define VERIFY3P(LEFT, OP, RIGHT) do { \ + const uintptr_t _verify3_left = (uintptr_t)(LEFT); \ + const uintptr_t _verify3_right = (uintptr_t)(RIGHT);\ + if (unlikely(!(_verify3_left OP _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ - "failed (%px " #OP " %px)\n", \ - (void *) (_verify3_left), \ - (void *) (_verify3_right)); \ + "failed (%px " #OP " %px)\n", \ + (void *) (_verify3_left), \ + (void *) (_verify3_right)); \ } while (0) -#define VERIFY0(RIGHT) do { \ - int64_t _verify3_left = (int64_t)(0); \ - int64_t _verify3_right = (int64_t)(RIGHT); \ - if (!(_verify3_left == _verify3_right)) \ +#define VERIFY0(RIGHT) do { \ + const int64_t _verify3_left = (int64_t)(0); \ + const int64_t _verify3_right = (int64_t)(RIGHT); \ + if (unlikely(!(_verify3_left == _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ - "VERIFY3(0 == " #RIGHT ") " \ - "failed (0 == %lld)\n", \ - (long long) (_verify3_right)); \ + "VERIFY3(0 == " #RIGHT ") " \ + "failed (0 == %lld)\n", \ + (long long) (_verify3_right)); \ } while (0) -#define CTASSERT_GLOBAL(x) CTASSERT(x) +#define CTASSERT_GLOBAL(x) CTASSERT(x) /* * Debugging disabled (--disable-debug) @@ -154,11 +154,11 @@ void spl_dumpstack(void); #define ASSERT0 VERIFY0 #define ASSERT VERIFY #define IMPLY(A, B) \ - ((void)(((!(A)) || (B)) || \ + ((void)(likely((!(A)) || (B)) || \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "(" #A ") implies (" #B ")"))) #define EQUIV(A, B) \ - ((void)((!!(A) == !!(B)) || \ + ((void)(likely(!!(A) == !!(B)) || \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "(" #A ") is equivalent to (" #B ")"))) /* END CSTYLED */ diff --git a/include/os/freebsd/zfs/sys/zfs_vfsops_os.h b/include/os/freebsd/zfs/sys/zfs_vfsops_os.h index c7f464d034bd..a263b48f7517 100644 --- a/include/os/freebsd/zfs/sys/zfs_vfsops_os.h +++ b/include/os/freebsd/zfs/sys/zfs_vfsops_os.h @@ -27,6 +27,10 @@ #ifndef _SYS_FS_ZFS_VFSOPS_H #define _SYS_FS_ZFS_VFSOPS_H +#if __FreeBSD_version >= 1300125 +#define TEARDOWN_RMS +#endif + #if __FreeBSD_version >= 1300109 #define TEARDOWN_INACTIVE_RMS #endif @@ -46,10 +50,16 @@ extern "C" { #endif -#ifdef TEARDOWN_INACTIVE_RMS +#ifdef TEARDOWN_RMS typedef struct rmslock zfs_teardown_lock_t; #else -#define zfs_teardown_lock_t krwlock_t +#define zfs_teardown_lock_t rrmlock_t +#endif + +#ifdef TEARDOWN_INACTIVE_RMS +typedef struct rmslock zfs_teardown_inactive_lock_t; +#else +#define zfs_teardown_inactive_lock_t krwlock_t #endif typedef struct zfsvfs zfsvfs_t; @@ -80,8 +90,8 @@ struct zfsvfs { int z_norm; /* normalization flags */ boolean_t z_atime; /* enable atimes mount option */ boolean_t z_unmounted; /* unmounted */ - rrmlock_t z_teardown_lock; - zfs_teardown_lock_t z_teardown_inactive_lock; + zfs_teardown_lock_t z_teardown_lock; + zfs_teardown_inactive_lock_t z_teardown_inactive_lock; list_t z_all_znodes; /* all vnodes in the fs */ uint64_t z_nr_znodes; /* number of znodes in the fs */ kmutex_t z_znodes_lock; /* lock for z_all_znodes */ @@ -112,53 +122,121 @@ struct zfsvfs { struct task z_unlinked_drain_task; }; +#ifdef TEARDOWN_RMS +#define ZFS_TEARDOWN_INIT(zfsvfs) \ + rms_init(&(zfsvfs)->z_teardown_lock, "zfs teardown") + +#define ZFS_TEARDOWN_DESTROY(zfsvfs) \ + rms_destroy(&(zfsvfs)->z_teardown_lock) + +#define ZFS_TEARDOWN_TRY_ENTER_READ(zfsvfs) \ + rms_try_rlock(&(zfsvfs)->z_teardown_lock) + +#define ZFS_TEARDOWN_ENTER_READ(zfsvfs, tag) \ + rms_rlock(&(zfsvfs)->z_teardown_lock); + +#define ZFS_TEARDOWN_EXIT_READ(zfsvfs, tag) \ + rms_runlock(&(zfsvfs)->z_teardown_lock) + +#define ZFS_TEARDOWN_ENTER_WRITE(zfsvfs, tag) \ + rms_wlock(&(zfsvfs)->z_teardown_lock) + +#define ZFS_TEARDOWN_EXIT_WRITE(zfsvfs) \ + rms_wunlock(&(zfsvfs)->z_teardown_lock) + +#define ZFS_TEARDOWN_EXIT(zfsvfs, tag) \ + rms_unlock(&(zfsvfs)->z_teardown_lock) + +#define ZFS_TEARDOWN_READ_HELD(zfsvfs) \ + rms_rowned(&(zfsvfs)->z_teardown_lock) + +#define ZFS_TEARDOWN_WRITE_HELD(zfsvfs) \ + rms_wowned(&(zfsvfs)->z_teardown_lock) + +#define ZFS_TEARDOWN_HELD(zfsvfs) \ + rms_owned_any(&(zfsvfs)->z_teardown_lock) +#else +#define ZFS_TEARDOWN_INIT(zfsvfs) \ + rrm_init(&(zfsvfs)->z_teardown_lock, B_FALSE) + +#define ZFS_TEARDOWN_DESTROY(zfsvfs) \ + rrm_destroy(&(zfsvfs)->z_teardown_lock) + +#define ZFS_TEARDOWN_TRY_ENTER_READ(zfsvfs) \ + rw_tryenter(&(zfsvfs)->z_teardown_lock, RW_READER) + +#define ZFS_TEARDOWN_ENTER_READ(zfsvfs, tag) \ + rrm_enter_read(&(zfsvfs)->z_teardown_lock, tag); + +#define ZFS_TEARDOWN_EXIT_READ(zfsvfs, tag) \ + rrm_exit(&(zfsvfs)->z_teardown_lock, tag) + +#define ZFS_TEARDOWN_ENTER_WRITE(zfsvfs, tag) \ + rrm_enter(&(zfsvfs)->z_teardown_lock, RW_WRITER, tag) + +#define ZFS_TEARDOWN_EXIT_WRITE(zfsvfs) \ + rrm_exit(&(zfsvfs)->z_teardown_lock, tag) + +#define ZFS_TEARDOWN_EXIT(zfsvfs, tag) \ + rrm_exit(&(zfsvfs)->z_teardown_lock, tag) + +#define ZFS_TEARDOWN_READ_HELD(zfsvfs) \ + RRM_READ_HELD(&(zfsvfs)->z_teardown_lock) + +#define ZFS_TEARDOWN_WRITE_HELD(zfsvfs) \ + RRM_WRITE_HELD(&(zfsvfs)->z_teardown_lock) + +#define ZFS_TEARDOWN_HELD(zfsvfs) \ + RRM_LOCK_HELD(&(zfsvfs)->z_teardown_lock) +#endif + #ifdef TEARDOWN_INACTIVE_RMS -#define ZFS_INIT_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_INIT(zfsvfs) \ rms_init(&(zfsvfs)->z_teardown_inactive_lock, "zfs teardown inactive") -#define ZFS_DESTROY_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_DESTROY(zfsvfs) \ rms_destroy(&(zfsvfs)->z_teardown_inactive_lock) -#define ZFS_TRYRLOCK_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_TRY_ENTER_READ(zfsvfs) \ rms_try_rlock(&(zfsvfs)->z_teardown_inactive_lock) -#define ZFS_RLOCK_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_ENTER_READ(zfsvfs) \ rms_rlock(&(zfsvfs)->z_teardown_inactive_lock) -#define ZFS_RUNLOCK_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_EXIT_READ(zfsvfs) \ rms_runlock(&(zfsvfs)->z_teardown_inactive_lock) -#define ZFS_WLOCK_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_ENTER_WRITE(zfsvfs) \ rms_wlock(&(zfsvfs)->z_teardown_inactive_lock) -#define ZFS_WUNLOCK_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs) \ rms_wunlock(&(zfsvfs)->z_teardown_inactive_lock) -#define ZFS_TEARDOWN_INACTIVE_WLOCKED(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_WRITE_HELD(zfsvfs) \ rms_wowned(&(zfsvfs)->z_teardown_inactive_lock) #else -#define ZFS_INIT_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_INIT(zfsvfs) \ rw_init(&(zfsvfs)->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL) -#define ZFS_DESTROY_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_DESTROY(zfsvfs) \ rw_destroy(&(zfsvfs)->z_teardown_inactive_lock) -#define ZFS_TRYRLOCK_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_TRY_ENTER_READ(zfsvfs) \ rw_tryenter(&(zfsvfs)->z_teardown_inactive_lock, RW_READER) -#define ZFS_RLOCK_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_ENTER_READ(zfsvfs) \ rw_enter(&(zfsvfs)->z_teardown_inactive_lock, RW_READER) -#define ZFS_RUNLOCK_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_EXIT_READ(zfsvfs) \ rw_exit(&(zfsvfs)->z_teardown_inactive_lock) -#define ZFS_WLOCK_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_ENTER_WRITE(zfsvfs) \ rw_enter(&(zfsvfs)->z_teardown_inactive_lock, RW_WRITER) -#define ZFS_WUNLOCK_TEARDOWN_INACTIVE(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_EXIT_WRITE(zfsvfs) \ rw_exit(&(zfsvfs)->z_teardown_inactive_lock) -#define ZFS_TEARDOWN_INACTIVE_WLOCKED(zfsvfs) \ +#define ZFS_TEARDOWN_INACTIVE_WRITE_HELD(zfsvfs) \ RW_WRITE_HELD(&(zfsvfs)->z_teardown_inactive_lock) #endif diff --git a/include/os/freebsd/zfs/sys/zfs_znode_impl.h b/include/os/freebsd/zfs/sys/zfs_znode_impl.h index 186afa9b2b39..d7cdb360c2bc 100644 --- a/include/os/freebsd/zfs/sys/zfs_znode_impl.h +++ b/include/os/freebsd/zfs/sys/zfs_znode_impl.h @@ -124,19 +124,19 @@ extern minor_t zfsdev_minor_alloc(void); /* Called on entry to each ZFS vnode and vfs operation */ #define ZFS_ENTER(zfsvfs) \ { \ - rrm_enter_read(&(zfsvfs)->z_teardown_lock, FTAG); \ - if ((zfsvfs)->z_unmounted) { \ - ZFS_EXIT(zfsvfs); \ + ZFS_TEARDOWN_ENTER_READ((zfsvfs), FTAG); \ + if (__predict_false((zfsvfs)->z_unmounted)) { \ + ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \ return (EIO); \ } \ } /* Must be called before exiting the vop */ -#define ZFS_EXIT(zfsvfs) rrm_exit(&(zfsvfs)->z_teardown_lock, FTAG) +#define ZFS_EXIT(zfsvfs) ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG) /* Verifies the znode is valid */ #define ZFS_VERIFY_ZP(zp) \ - if ((zp)->z_sa_hdl == NULL) { \ + if (__predict_false((zp)->z_sa_hdl == NULL)) { \ ZFS_EXIT((zp)->z_zfsvfs); \ return (EIO); \ } \ diff --git a/include/os/linux/spl/sys/debug.h b/include/os/linux/spl/sys/debug.h index 46da5c783397..dc6b85eebff7 100644 *** 2070 LINES SKIPPED ***