The branch stable/13 has been updated by mm:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=cf2a72643460a2bb50fcdf78fb8721a692315793

commit cf2a72643460a2bb50fcdf78fb8721a692315793
Author:     Martin Matuska <[email protected]>
AuthorDate: 2021-03-14 01:23:51 +0000
Commit:     Martin Matuska <[email protected]>
CommitDate: 2021-04-04 13:18:45 +0000

    zfs: merge OpenZFS 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
    
    Obtained from:  OpenZFS
    
    (cherry picked from commit 9db44a8e5da9bf1ce6dd1c0f1468ddafed6d6c91)
---
 .../openzfs/.github/workflows/checkstyle.yaml      |   2 +-
 sys/contrib/openzfs/cmd/vdev_id/vdev_id            |   9 +-
 sys/contrib/openzfs/cmd/zpool/zpool_main.c         | 307 +++++++++++++--------
 sys/contrib/openzfs/cmd/zstream/zstream_redup.c    |   1 +
 sys/contrib/openzfs/config/zfs-build.m4            |  36 +++
 sys/contrib/openzfs/configure.ac                   |   1 +
 .../openzfs/include/os/freebsd/spl/sys/Makefile.am |   3 +
 .../openzfs/include/os/freebsd/spl/sys/debug.h     |  80 +++---
 .../include/os/freebsd/zfs/sys/zfs_vfsops_os.h     |   2 +-
 .../openzfs/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      |   4 +-
 sys/contrib/openzfs/include/sys/dmu_redact.h       |   2 +
 sys/contrib/openzfs/include/sys/zfs_ioctl.h        |   1 -
 sys/contrib/openzfs/lib/libzfs/libzfs_crypto.c     |  10 +-
 sys/contrib/openzfs/lib/libzfs/libzfs_mount.c      |  25 +-
 .../openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c  |   5 +-
 .../openzfs/lib/libzfs/os/linux/libzfs_mount_os.c  |   6 +-
 sys/contrib/openzfs/lib/libzutil/zutil_import.c    | 177 +++++++++---
 sys/contrib/openzfs/man/man8/zfs-receive.8         |  10 +
 sys/contrib/openzfs/man/man8/zfs-send.8            |   7 +-
 sys/contrib/openzfs/module/Makefile.in             |   5 +
 .../openzfs/module/os/freebsd/zfs/kmod_core.c      |  18 +-
 .../openzfs/module/os/freebsd/zfs/zfs_dir.c        |   2 -
 .../openzfs/module/os/freebsd/zfs/zvol_os.c        |   9 +-
 sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c  |  26 +-
 .../openzfs/module/os/linux/zfs/zio_crypt.c        |   1 +
 sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c  | 102 +++++--
 sys/contrib/openzfs/module/zcommon/zfs_prop.c      |   2 +-
 sys/contrib/openzfs/module/zfs/abd.c               |   6 +-
 sys/contrib/openzfs/module/zfs/spa_misc.c          |   4 +-
 sys/contrib/openzfs/module/zfs/zfs_vnops.c         |   6 +-
 sys/contrib/openzfs/module/zfs/zvol.c              |  15 +-
 sys/contrib/openzfs/tests/runfiles/common.run      |   1 +
 .../openzfs/tests/zfs-tests/include/commands.cfg   |   2 +-
 .../openzfs/tests/zfs-tests/include/libtest.shlib  |  19 +-
 .../openzfs/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 +--
 sys/modules/zfs/zfs_config.h                       |   4 +-
 44 files changed, 896 insertions(+), 378 deletions(-)

diff --git a/sys/contrib/openzfs/.github/workflows/checkstyle.yaml 
b/sys/contrib/openzfs/.github/workflows/checkstyle.yaml
index 1707f5bb21db..8dcd5047a748 100644
--- a/sys/contrib/openzfs/.github/workflows/checkstyle.yaml
+++ b/sys/contrib/openzfs/.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/sys/contrib/openzfs/cmd/vdev_id/vdev_id 
b/sys/contrib/openzfs/cmd/vdev_id/vdev_id
index 8a379a72690e..d8918da1078c 100755
--- a/sys/contrib/openzfs/cmd/vdev_id/vdev_id
+++ b/sys/contrib/openzfs/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/sys/contrib/openzfs/cmd/zpool/zpool_main.c 
b/sys/contrib/openzfs/cmd/zpool/zpool_main.c
index e89eb3bea770..e23604b3d81c 100644
--- a/sys/contrib/openzfs/cmd/zpool/zpool_main.c
+++ b/sys/contrib/openzfs/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] <pool | id> [newpool]
+ *              [-d dir | -c cachefile | -s] [-f] [-n] [-F] <pool | id>
+ *              [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/sys/contrib/openzfs/cmd/zstream/zstream_redup.c 
b/sys/contrib/openzfs/cmd/zstream/zstream_redup.c
index 41f1068e3dfc..15dd8a1ed126 100644
--- a/sys/contrib/openzfs/cmd/zstream/zstream_redup.c
+++ b/sys/contrib/openzfs/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/sys/contrib/openzfs/config/zfs-build.m4 
b/sys/contrib/openzfs/config/zfs-build.m4
index 305d0c6936b2..cd5996c0424c 100644
--- a/sys/contrib/openzfs/config/zfs-build.m4
+++ b/sys/contrib/openzfs/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/sys/contrib/openzfs/configure.ac b/sys/contrib/openzfs/configure.ac
index b2d88554ed7d..07f590b390bd 100644
--- a/sys/contrib/openzfs/configure.ac
+++ b/sys/contrib/openzfs/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/sys/contrib/openzfs/include/os/freebsd/spl/sys/Makefile.am 
b/sys/contrib/openzfs/include/os/freebsd/spl/sys/Makefile.am
index ca45b42b6b8d..6bee47830d9c 100644
--- a/sys/contrib/openzfs/include/os/freebsd/spl/sys/Makefile.am
+++ b/sys/contrib/openzfs/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/sys/contrib/openzfs/include/os/freebsd/spl/sys/debug.h 
b/sys/contrib/openzfs/include/os/freebsd/spl/sys/debug.h
index 2751f57801f7..1f820bc3345f 100644
--- a/sys/contrib/openzfs/include/os/freebsd/spl/sys/debug.h
+++ b/sys/contrib/openzfs/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/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_vfsops_os.h 
b/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_vfsops_os.h
index 5d8e5978a3cb..a263b48f7517 100644
--- a/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_vfsops_os.h
+++ b/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_vfsops_os.h
@@ -27,7 +27,7 @@
 #ifndef        _SYS_FS_ZFS_VFSOPS_H
 #define        _SYS_FS_ZFS_VFSOPS_H
 
-#if __FreeBSD_version >= 1300109
+#if __FreeBSD_version >= 1300125
 #define        TEARDOWN_RMS
 #endif
 
diff --git a/sys/contrib/openzfs/include/os/linux/spl/sys/debug.h 
b/sys/contrib/openzfs/include/os/linux/spl/sys/debug.h
index 46da5c783397..dc6b85eebff7 100644
--- a/sys/contrib/openzfs/include/os/linux/spl/sys/debug.h
+++ b/sys/contrib/openzfs/include/os/linux/spl/sys/debug.h
@@ -62,63 +62,63 @@ 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, __LINE__)
@@ -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/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vfsops_os.h 
b/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vfsops_os.h
index 24a0a2e6a05f..7b4a1aac9aad 100644
--- a/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vfsops_os.h
+++ b/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vfsops_os.h
@@ -138,6 +138,39 @@ struct zfsvfs {
        taskqid_t       z_drain_task;   /* task id for the unlink drain task */
 };
 
+#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)
+
 #define        ZSB_XATTR       0x0001          /* Enable user xattrs */
 
 /*
diff --git a/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_znode_impl.h 
b/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_znode_impl.h
index 41bdf932511d..b1b3aec4c70f 100644
--- a/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_znode_impl.h
+++ b/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_znode_impl.h
@@ -81,7 +81,7 @@ extern "C" {
 do {                                                           \
        ZFS_TEARDOWN_ENTER_READ(zfsvfs, FTAG);                  \
        if (unlikely((zfsvfs)->z_unmounted)) {                  \
-               ZFS_EXIT_READ(zfsvfs, FTAG);                    \
+               ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG);           \
                return (error);                                 \
        }                                                       \
 } while (0)
@@ -92,7 +92,7 @@ do {                                                          
\
 #define        ZFS_EXIT(zfsvfs)                                        \
 do {                                                           \
        zfs_exit_fs(zfsvfs);                                    \
-       ZFS_EXIT_READ(zfsvfs, FTAG);                            \
+       ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG);                   \
 } while (0)
 
 #define        ZPL_EXIT(zfsvfs)                                        \
diff --git a/sys/contrib/openzfs/include/sys/dmu_redact.h 
b/sys/contrib/openzfs/include/sys/dmu_redact.h
index 207fdbb5cfda..85f4b0522891 100644
--- a/sys/contrib/openzfs/include/sys/dmu_redact.h
+++ b/sys/contrib/openzfs/include/sys/dmu_redact.h
@@ -39,6 +39,7 @@ redact_block_get_size(redact_block_phys_t *rbp)
 static inline void
 redact_block_set_size(redact_block_phys_t *rbp, uint64_t size)
 {
+       /* cppcheck-suppress syntaxError */
        BF64_SET_SB((rbp)->rbp_size_count, 48, 16, SPA_MINBLOCKSHIFT, 0, size);
 }
 
@@ -51,6 +52,7 @@ redact_block_get_count(redact_block_phys_t *rbp)
 static inline void
 redact_block_set_count(redact_block_phys_t *rbp, uint64_t count)
 {
+       /* cppcheck-suppress syntaxError */
*** 1423 LINES SKIPPED ***
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to