aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2021-03-14 01:23:51 +0000
committerMartin Matuska <mm@FreeBSD.org>2021-04-04 13:18:45 +0000
commitcf2a72643460a2bb50fcdf78fb8721a692315793 (patch)
treeefa442c1e0902d1e9b49d7e8503d5feb675bfedf
parent1260724822b5830411cbf56d48e997be1628e53b (diff)
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)
-rw-r--r--sys/contrib/openzfs/.github/workflows/checkstyle.yaml2
-rwxr-xr-xsys/contrib/openzfs/cmd/vdev_id/vdev_id9
-rw-r--r--sys/contrib/openzfs/cmd/zpool/zpool_main.c307
-rw-r--r--sys/contrib/openzfs/cmd/zstream/zstream_redup.c1
-rw-r--r--sys/contrib/openzfs/config/zfs-build.m436
-rw-r--r--sys/contrib/openzfs/configure.ac1
-rw-r--r--sys/contrib/openzfs/include/os/freebsd/spl/sys/Makefile.am3
-rw-r--r--sys/contrib/openzfs/include/os/freebsd/spl/sys/debug.h80
-rw-r--r--sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_vfsops_os.h2
-rw-r--r--sys/contrib/openzfs/include/os/linux/spl/sys/debug.h78
-rw-r--r--sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vfsops_os.h33
-rw-r--r--sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_znode_impl.h4
-rw-r--r--sys/contrib/openzfs/include/sys/dmu_redact.h2
-rw-r--r--sys/contrib/openzfs/include/sys/zfs_ioctl.h1
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_crypto.c10
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_mount.c25
-rw-r--r--sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c5
-rw-r--r--sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c6
-rw-r--r--sys/contrib/openzfs/lib/libzutil/zutil_import.c177
-rw-r--r--sys/contrib/openzfs/man/man8/zfs-receive.810
-rw-r--r--sys/contrib/openzfs/man/man8/zfs-send.87
-rw-r--r--sys/contrib/openzfs/module/Makefile.in5
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/kmod_core.c18
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/zfs_dir.c2
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c9
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c26
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c1
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c102
-rw-r--r--sys/contrib/openzfs/module/zcommon/zfs_prop.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/abd.c6
-rw-r--r--sys/contrib/openzfs/module/zfs/spa_misc.c4
-rw-r--r--sys/contrib/openzfs/module/zfs/zfs_vnops.c6
-rw-r--r--sys/contrib/openzfs/module/zfs/zvol.c15
-rw-r--r--sys/contrib/openzfs/tests/runfiles/common.run1
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg2
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib19
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg8
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh37
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh39
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_import/Makefile.am1
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_paths_changed.ksh117
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/events/events_002_pos.ksh7
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/xattr/xattr_003_neg.ksh44
-rw-r--r--sys/modules/zfs/zfs_config.h4
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 */
BF64_SET_SB((rbp)->rbp_size_count, 0, 48, 0, 1, count);
}
diff --git a/sys/contrib/openzfs/include/sys/zfs_ioctl.h b/sys/contrib/openzfs/include/sys/zfs_ioctl.h
index afae576ea21a..8834c52990d0 100644
--- a/sys/contrib/openzfs/include/sys/zfs_ioctl.h
+++ b/sys/contrib/openzfs/include/sys/zfs_ioctl.h
@@ -525,7 +525,6 @@ typedef struct zfs_useracct {
} zfs_useracct_t;
#define ZFSDEV_MAX_MINOR (1 << 16)
-#define ZFS_MIN_MINOR (ZFSDEV_MAX_MINOR + 1)
#define ZPOOL_EXPORT_AFTER_SPLIT 0x1
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_crypto.c b/sys/contrib/openzfs/lib/libzfs/libzfs_crypto.c
index 1a2ee638aef3..fe3a0f28360e 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_crypto.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_crypto.c
@@ -532,6 +532,8 @@ get_key_material(libzfs_handle_t *hdl, boolean_t do_verify, boolean_t newkey,
break;
case ZFS_KEYLOCATION_URI:
+ ret = ENOTSUP;
+
for (handler = uri_handlers; handler->zuh_scheme != NULL;
handler++) {
if (strcmp(handler->zuh_scheme, uri_scheme) != 0)
@@ -544,9 +546,11 @@ get_key_material(libzfs_handle_t *hdl, boolean_t do_verify, boolean_t newkey,
break;
}
- ret = ENOTSUP;
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "URI scheme is not supported"));
+ if (ret == ENOTSUP) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "URI scheme is not supported"));
+ goto error;
+ }
break;
default:
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c b/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c
index 6d11016bca4e..2a543daac9ae 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c
@@ -22,7 +22,7 @@
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2014, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2014, 2021 by Delphix. All rights reserved.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
* Copyright 2017 RackTop Systems.
* Copyright (c) 2018 Datto Inc.
@@ -553,7 +553,28 @@ unmount_one(libzfs_handle_t *hdl, const char *mountpoint, int flags)
error = do_unmount(mountpoint, flags);
if (error != 0) {
- return (zfs_error_fmt(hdl, EZFS_UMOUNTFAILED,
+ int libzfs_err;
+
+ switch (error) {
+ case EBUSY:
+ libzfs_err = EZFS_BUSY;
+ break;
+ case EIO:
+ libzfs_err = EZFS_IO;
+ break;
+ case ENOENT:
+ libzfs_err = EZFS_NOENT;
+ break;
+ case ENOMEM:
+ libzfs_err = EZFS_NOMEM;
+ break;
+ case EPERM:
+ libzfs_err = EZFS_PERM;
+ break;
+ default:
+ libzfs_err = EZFS_UMOUNTFAILED;
+ }
+ return (zfs_error_fmt(hdl, libzfs_err,
dgettext(TEXT_DOMAIN, "cannot unmount '%s'"),
mountpoint));
}
diff --git a/sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c b/sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c
index 2207fffc5573..e114b1e0ca6f 100644
--- a/sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c
+++ b/sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c
@@ -128,8 +128,9 @@ do_mount(zfs_handle_t *zhp, const char *mntpt, char *opts, int flags)
int
do_unmount(const char *mntpt, int flags)
{
-
- return (unmount(mntpt, flags));
+ if (unmount(mntpt, flags) < 0)
+ return (errno);
+ return (0);
}
int
diff --git a/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c b/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c
index 92052f28ffe7..21d64053862e 100644
--- a/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c
+++ b/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c
@@ -22,7 +22,7 @@
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2014, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2014, 2021 by Delphix. All rights reserved.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
* Copyright 2017 RackTop Systems.
* Copyright (c) 2018 Datto Inc.
@@ -377,7 +377,9 @@ int
do_unmount(const char *mntpt, int flags)
{
if (!libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) {
- return (umount2(mntpt, flags));
+ int rv = umount2(mntpt, flags);
+
+ return (rv < 0 ? errno : 0);
}
char force_opt[] = "-f";
diff --git a/sys/contrib/openzfs/lib/libzutil/zutil_import.c b/sys/contrib/openzfs/lib/libzutil/zutil_import.c
index b9e08eac6af0..e1f31b385503 100644
--- a/sys/contrib/openzfs/lib/libzutil/zutil_import.c
+++ b/sys/contrib/openzfs/lib/libzutil/zutil_import.c
@@ -1269,7 +1269,8 @@ error:
* to import a specific pool.
*/
static nvlist_t *
-zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg)
+zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg,
+ pthread_mutex_t *lock, avl_tree_t *cache)
{
nvlist_t *ret = NULL;
pool_list_t pools = { 0 };
@@ -1277,34 +1278,11 @@ zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg)
vdev_entry_t *ve, *venext;
config_entry_t *ce, *cenext;
name_entry_t *ne, *nenext;
- pthread_mutex_t lock;
- avl_tree_t *cache;
rdsk_node_t *slice;
void *cookie;
tpool_t *t;
verify(iarg->poolname == NULL || iarg->guid == 0);
- pthread_mutex_init(&lock, NULL);
-
- /*
- * Locate pool member vdevs by blkid or by directory scanning.
- * On success a newly allocated AVL tree which is populated with an
- * entry for each discovered vdev will be returned in the cache.
- * It's the caller's responsibility to consume and destroy this tree.
- */
- if (iarg->scan || iarg->paths != 0) {
- size_t dirs = iarg->paths;
- const char * const *dir = (const char * const *)iarg->path;
-
- if (dirs == 0)
- dir = zpool_default_search_paths(&dirs);
-
- if (zpool_find_import_scan(hdl, &lock, &cache, dir, dirs) != 0)
- return (NULL);
- } else {
- if (zpool_find_import_blkid(hdl, &lock, &cache) != 0)
- return (NULL);
- }
/*
* Create a thread pool to parallelize the process of reading and
@@ -1384,7 +1362,6 @@ zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg)
}
avl_destroy(cache);
free(cache);
- pthread_mutex_destroy(&lock);
ret = get_configs(hdl, &pools, iarg->can_be_active, iarg->policy);
@@ -1412,13 +1389,42 @@ zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg)
}
/*
+ * Given a config, discover the paths for the devices which
+ * exist in the config.
+ */
+static int
+discover_cached_paths(libpc_handle_t *hdl, nvlist_t *nv,
+ avl_tree_t *cache, pthread_mutex_t *lock)
+{
+ char *path = NULL;
+ uint_t children;
+ nvlist_t **child;
+
+ if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
+ &child, &children) == 0) {
+ for (int c = 0; c < children; c++) {
+ discover_cached_paths(hdl, child[c], cache, lock);
+ }
+ }
+
+ /*
+ * Once we have the path, we need to add the directory to
+ * our directoy cache.
+ */
+ if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
+ return (zpool_find_import_scan_dir(hdl, lock, cache,
+ dirname(path), 0));
+ }
+ return (0);
+}
+
+/*
* Given a cache file, return the contents as a list of importable pools.
* poolname or guid (but not both) are provided by the caller when trying
* to import a specific pool.
*/
static nvlist_t *
-zpool_find_import_cached(libpc_handle_t *hdl, const char *cachefile,
- const char *poolname, uint64_t guid)
+zpool_find_import_cached(libpc_handle_t *hdl, importargs_t *iarg)
{
char *buf;
int fd;
@@ -1430,9 +1436,9 @@ zpool_find_import_cached(libpc_handle_t *hdl, const char *cachefile,
uint64_t this_guid;
boolean_t active;
- verify(poolname == NULL || guid == 0);
+ verify(iarg->poolname == NULL || iarg->guid == 0);
- if ((fd = open(cachefile, O_RDONLY)) < 0) {
+ if ((fd = open(iarg->cachefile, O_RDONLY)) < 0) {
zutil_error_aux(hdl, "%s", strerror(errno));
(void) zutil_error(hdl, EZFS_BADCACHE,
dgettext(TEXT_DOMAIN, "failed to open cache file"));
@@ -1488,11 +1494,11 @@ zpool_find_import_cached(libpc_handle_t *hdl, const char *cachefile,
src = fnvpair_value_nvlist(elem);
name = fnvlist_lookup_string(src, ZPOOL_CONFIG_POOL_NAME);
- if (poolname != NULL && strcmp(poolname, name) != 0)
+ if (iarg->poolname != NULL && strcmp(iarg->poolname, name) != 0)
continue;
this_guid = fnvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID);
- if (guid != 0 && guid != this_guid)
+ if (iarg->guid != 0 && iarg->guid != this_guid)
continue;
if (zutil_pool_active(hdl, name, this_guid, &active) != 0) {
@@ -1504,8 +1510,68 @@ zpool_find_import_cached(libpc_handle_t *hdl, const char *cachefile,
if (active)
continue;
+ if (iarg->scan) {
+ uint64_t saved_guid = iarg->guid;
+ const char *saved_poolname = iarg->poolname;
+ pthread_mutex_t lock;
+
+ /*
+ * Create the device cache that will hold the
+ * devices we will scan based on the cachefile.
+ * This will get destroyed and freed by
+ * zpool_find_import_impl.
+ */
+ avl_tree_t *cache = zutil_alloc(hdl,
+ sizeof (avl_tree_t));
+ avl_create(cache, slice_cache_compare,
+ sizeof (rdsk_node_t),
+ offsetof(rdsk_node_t, rn_node));
+ nvlist_t *nvroot = fnvlist_lookup_nvlist(src,
+ ZPOOL_CONFIG_VDEV_TREE);
+
+ /*
+ * We only want to find the pool with this_guid.
+ * We will reset these values back later.
+ */
+ iarg->guid = this_guid;
+ iarg->poolname = NULL;
+
+ /*
+ * We need to build up a cache of devices that exists
+ * in the paths pointed to by the cachefile. This allows
+ * us to preserve the device namespace that was
+ * originally specified by the user but also lets us
+ * scan devices in those directories in case they had
+ * been renamed.
+ */
+ pthread_mutex_init(&lock, NULL);
+ discover_cached_paths(hdl, nvroot, cache, &lock);
+ nvlist_t *nv = zpool_find_import_impl(hdl, iarg,
+ &lock, cache);
+ pthread_mutex_destroy(&lock);
+
+ /*
+ * zpool_find_import_impl will return back
+ * a list of pools that it found based on the
+ * device cache. There should only be one pool
+ * since we're looking for a specific guid.
+ * We will use that pool to build up the final
+ * pool nvlist which is returned back to the
+ * caller.
+ */
+ nvpair_t *pair = nvlist_next_nvpair(nv, NULL);
+ fnvlist_add_nvlist(pools, nvpair_name(pair),
+ fnvpair_value_nvlist(pair));
+
+ VERIFY3P(nvlist_next_nvpair(nv, pair), ==, NULL);
+
+ iarg->guid = saved_guid;
+ iarg->poolname = saved_poolname;
+ continue;
+ }
+
if (nvlist_add_string(src, ZPOOL_CONFIG_CACHEFILE,
- cachefile) != 0) {
+ iarg->cachefile) != 0) {
(void) zutil_no_memory(hdl);
nvlist_free(raw);
nvlist_free(pools);
@@ -1527,11 +1593,51 @@ zpool_find_import_cached(libpc_handle_t *hdl, const char *cachefile,
}
nvlist_free(dst);
}
-
nvlist_free(raw);
return (pools);
}
+static nvlist_t *
+zpool_find_import(libpc_handle_t *hdl, importargs_t *iarg)
+{
+ pthread_mutex_t lock;
+ avl_tree_t *cache;
+ nvlist_t *pools = NULL;
+
+ verify(iarg->poolname == NULL || iarg->guid == 0);
+ pthread_mutex_init(&lock, NULL);
+
+ /*
+ * Locate pool member vdevs by blkid or by directory scanning.
+ * On success a newly allocated AVL tree which is populated with an
+ * entry for each discovered vdev will be returned in the cache.
+ * It's the caller's responsibility to consume and destroy this tree.
+ */
+ if (iarg->scan || iarg->paths != 0) {
+ size_t dirs = iarg->paths;
+ const char * const *dir = (const char * const *)iarg->path;
+
+ if (dirs == 0)
+ dir = zpool_default_search_paths(&dirs);
+
+ if (zpool_find_import_scan(hdl, &lock, &cache,
+ dir, dirs) != 0) {
+ pthread_mutex_destroy(&lock);
+ return (NULL);
+ }
+ } else {
+ if (zpool_find_import_blkid(hdl, &lock, &cache) != 0) {
+ pthread_mutex_destroy(&lock);
+ return (NULL);
+ }
+ }
+
+ pools = zpool_find_import_impl(hdl, iarg, &lock, cache);
+ pthread_mutex_destroy(&lock);
+ return (pools);
+}
+
+
nvlist_t *
zpool_search_import(void *hdl, importargs_t *import,
const pool_config_ops_t *pco)
@@ -1546,10 +1652,9 @@ zpool_search_import(void *hdl, importargs_t *import,
verify(import->poolname == NULL || import->guid == 0);
if (import->cachefile != NULL)
- pools = zpool_find_import_cached(&handle, import->cachefile,
- import->poolname, import->guid);
+ pools = zpool_find_import_cached(&handle, import);
else
- pools = zpool_find_import_impl(&handle, import);
+ pools = zpool_find_import(&handle, import);
if ((pools == NULL || nvlist_empty(pools)) &&
handle.lpc_open_access_error && geteuid() != 0) {
diff --git a/sys/contrib/openzfs/man/man8/zfs-receive.8 b/sys/contrib/openzfs/man/man8/zfs-receive.8
index ed5cbbdf0b79..36ed2050683a 100644
--- a/sys/contrib/openzfs/man/man8/zfs-receive.8
+++ b/sys/contrib/openzfs/man/man8/zfs-receive.8
@@ -261,6 +261,16 @@ causes the property to be inherited by all descendant datasets, as through
was run on any descendant datasets that have this property set on the
sending system.
.Pp
+If the send stream was sent with
+.Fl c
+then overriding the
+.Sy compression
+property will have no affect on received data but the
+.Sy compression
+property will be set. To have the data recompressed on receive remove the
+.Fl c
+flag from the send stream.
+.Pp
Any editable property can be set at receive time. Set-once properties bound
to the received data, such as
.Sy normalization
diff --git a/sys/contrib/openzfs/man/man8/zfs-send.8 b/sys/contrib/openzfs/man/man8/zfs-send.8
index 1a241a52d54b..4156db4f6b47 100644
--- a/sys/contrib/openzfs/man/man8/zfs-send.8
+++ b/sys/contrib/openzfs/man/man8/zfs-send.8
@@ -189,7 +189,12 @@ feature is enabled on the sending system but the
option is not supplied in conjunction with
.Fl c ,
then the data will be decompressed before sending so it can be split into
-smaller block sizes.
+smaller block sizes. Streams sent with
+.Fl c
+will not have their data recompressed on the receiver side using
+.Fl o compress=value.
+The data will stay compressed as it was from the sender. The new compression
+property will be set for future data.
.It Fl w, -raw
For encrypted datasets, send data exactly as it exists on disk. This allows
backups to be taken even if encryption keys are not currently loaded. The
diff --git a/sys/contrib/openzfs/module/Makefile.in b/sys/contrib/openzfs/module/Makefile.in
index 69caf48570e9..089b3ff88490 100644
--- a/sys/contrib/openzfs/module/Makefile.in
+++ b/sys/contrib/openzfs/module/Makefile.in
@@ -17,6 +17,10 @@ check:
modules_uninstall modules_uninstall-Linux modules_uninstall-FreeBSD \
cppcheck cppcheck-Linux cppcheck-FreeBSD
+# For FreeBSD, use debug options from ./configure if not overridden.
+export WITH_DEBUG ?= @WITH_DEBUG@
+export WITH_INVARIANTS ?= @WITH_INVARIANTS@
+
# Filter out options that FreeBSD make doesn't understand
getflags = ( \
set -- \
@@ -42,6 +46,7 @@ FMAKEFLAGS = -C @abs_srcdir@ -f Makefile.bsd $(shell $(getflags))
ifneq (@abs_srcdir@,@abs_builddir@)
FMAKEFLAGS += MAKEOBJDIR=@abs_builddir@
endif
+
FMAKE = env -u MAKEFLAGS make $(FMAKEFLAGS)
modules-Linux:
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/kmod_core.c b/sys/contrib/openzfs/module/os/freebsd/zfs/kmod_core.c
index c11d4dbcf660..d5ba0d93a569 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/kmod_core.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/kmod_core.c
@@ -182,23 +182,21 @@ out:
static void
zfsdev_close(void *data)
{
- zfsdev_state_t *zs, *zsp = data;
+ zfsdev_state_t *zs = data;
+
+ ASSERT(zs != NULL);
mutex_enter(&zfsdev_state_lock);
- for (zs = zfsdev_state_list; zs != NULL; zs = zs->zs_next) {
- if (zs == zsp)
- break;
- }
- if (zs == NULL || zs->zs_minor <= 0) {
- mutex_exit(&zfsdev_state_lock);
- return;
- }
+
+ ASSERT(zs->zs_minor != 0);
+
zs->zs_minor = -1;
zfs_onexit_destroy(zs->zs_onexit);
zfs_zevent_destroy(zs->zs_zevent);
- mutex_exit(&zfsdev_state_lock);
zs->zs_onexit = NULL;
zs->zs_zevent = NULL;
+
+ mutex_exit(&zfsdev_state_lock);
}
static int
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_dir.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_dir.c
index fb01012dd6e7..de145a677600 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_dir.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_dir.c
@@ -209,7 +209,6 @@ zfs_dd_lookup(znode_t *dzp, znode_t **zpp)
#ifdef ZFS_DEBUG
if (zfsvfs->z_replay == B_FALSE)
ASSERT_VOP_LOCKED(ZTOV(dzp), __func__);
- ASSERT(ZFS_TEARDOWN_READ_HELD(zfsvfs));
#endif
if (dzp->z_unlinked)
return (ENOENT);
@@ -234,7 +233,6 @@ zfs_dirlook(znode_t *dzp, const char *name, znode_t **zpp)
#ifdef ZFS_DEBUG
if (zfsvfs->z_replay == B_FALSE)
ASSERT_VOP_LOCKED(ZTOV(dzp), __func__);
- ASSERT(ZFS_TEARDOWN_READ_HELD(zfsvfs));
#endif
if (dzp->z_unlinked)
return (SET_ERROR(ENOENT));
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c
index 2389b1a06355..ba315f104738 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c
@@ -1163,6 +1163,9 @@ zvol_ensure_zilog(zvol_state_t *zv)
zv->zv_zilog = zil_open(zv->zv_objset,
zvol_get_data);
zv->zv_flags |= ZVOL_WRITTEN_TO;
+ /* replay / destroy done in zvol_create_minor_impl() */
+ VERIFY0((zv->zv_zilog->zl_header->zh_flags &
+ ZIL_REPLAY_NEEDED));
}
rw_downgrade(&zv->zv_suspend_lock);
}
@@ -1387,12 +1390,16 @@ zvol_create_minor_impl(const char *name)
zv->zv_volsize = volsize;
zv->zv_objset = os;
+ ASSERT3P(zv->zv_zilog, ==, NULL);
+ zv->zv_zilog = zil_open(os, zvol_get_data);
if (spa_writeable(dmu_objset_spa(os))) {
if (zil_replay_disable)
- zil_destroy(dmu_objset_zil(os), B_FALSE);
+ zil_destroy(zv->zv_zilog, B_FALSE);
else
zil_replay(os, zv, zvol_replay_vector);
}
+ zil_close(zv->zv_zilog);
+ zv->zv_zilog = NULL;
ASSERT3P(zv->zv_kstat.dk_kstats, ==, NULL);
dataset_kstats_create(&zv->zv_kstat, zv->zv_objset);
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c
index 2628325c0ba9..f8bf55f75e97 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c
@@ -2214,13 +2214,11 @@ zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode)
}
/*
- * Only check for READONLY on non-directories.
+ * Intentionally allow ZFS_READONLY through here.
+ * See zfs_zaccess_common().
*/
if ((v4_mode & WRITE_MASK_DATA) &&
- ((!S_ISDIR(ZTOI(zp)->i_mode) &&
- (zp->z_pflags & (ZFS_READONLY | ZFS_IMMUTABLE))) ||
- (S_ISDIR(ZTOI(zp)->i_mode) &&
- (zp->z_pflags & ZFS_IMMUTABLE)))) {
+ (zp->z_pflags & ZFS_IMMUTABLE)) {
return (SET_ERROR(EPERM));
}
@@ -2434,6 +2432,24 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
return (0);
}
+ /*
+ * Note: ZFS_READONLY represents the "DOS R/O" attribute.
+ * When that flag is set, we should behave as if write access
+ * were not granted by anything in the ACL. In particular:
+ * We _must_ allow writes after opening the file r/w, then
+ * setting the DOS R/O attribute, and writing some more.
+ * (Similar to how you can write after fchmod(fd, 0444).)
+ *
+ * Therefore ZFS_READONLY is ignored in the dataset check
+ * above, and checked here as if part of the ACL check.
+ * Also note: DOS R/O is ignored for directories.
+ */
+ if ((v4_mode & WRITE_MASK_DATA) &&
+ S_ISDIR(ZTOI(zp)->i_mode) &&
+ (zp->z_pflags & ZFS_READONLY)) {
+ return (SET_ERROR(EPERM));
+ }
+
return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr));
}
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c b/sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c
index 284ca706ede5..2c58fecb2066 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c
@@ -1412,6 +1412,7 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
nr_src = 1;
nr_dst = 0;
}
+ bzero(dst, datalen);
/* find the start and end record of the log block */
zilc = (zil_chain_t *)src;
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c b/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c
index 0d62b1490702..7756d819fdeb 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c
@@ -56,12 +56,32 @@ struct zvol_state_os {
taskq_t *zvol_taskq;
static struct ida zvol_ida;
-typedef struct zv_request {
+typedef struct zv_request_stack {
zvol_state_t *zv;
struct bio *bio;
- taskq_ent_t ent;
} zv_request_t;
+typedef struct zv_request_task {
+ zv_request_t zvr;
+ taskq_ent_t ent;
+} zv_request_task_t;
+
+static zv_request_task_t *
+zv_request_task_create(zv_request_t zvr)
+{
+ zv_request_task_t *task;
+ task = kmem_alloc(sizeof (zv_request_task_t), KM_SLEEP);
+ taskq_init_ent(&task->ent);
+ task->zvr = zvr;
+ return (task);
+}
+
+static void
+zv_request_task_free(zv_request_task_t *task)
+{
+ kmem_free(task, sizeof (*task));
+}
+
/*
* Given a path, return TRUE if path is a ZVOL.
*/
@@ -80,9 +100,8 @@ zvol_is_zvol_impl(const char *path)
}
static void
-zvol_write(void *arg)
+zvol_write(zv_request_t *zvr)
{
- zv_request_t *zvr = arg;
struct bio *bio = zvr->bio;
int error = 0;
zfs_uio_t uio;
@@ -102,7 +121,6 @@ zvol_write(void *arg)
if (uio.uio_resid == 0) {
rw_exit(&zv->zv_suspend_lock);
BIO_END_IO(bio, 0);
- kmem_free(zvr, sizeof (zv_request_t));
return;
}
@@ -162,13 +180,19 @@ zvol_write(void *arg)
blk_generic_end_io_acct(q, disk, WRITE, bio, start_time);
BIO_END_IO(bio, -error);
- kmem_free(zvr, sizeof (zv_request_t));
}
static void
-zvol_discard(void *arg)
+zvol_write_task(void *arg)
+{
+ zv_request_task_t *task = arg;
+ zvol_write(&task->zvr);
+ zv_request_task_free(task);
+}
+
+static void
+zvol_discard(zv_request_t *zvr)
{
- zv_request_t *zvr = arg;
struct bio *bio = zvr->bio;
zvol_state_t *zv = zvr->zv;
uint64_t start = BIO_BI_SECTOR(bio) << 9;
@@ -238,13 +262,19 @@ unlock:
blk_generic_end_io_acct(q, disk, WRITE, bio, start_time);
BIO_END_IO(bio, -error);
- kmem_free(zvr, sizeof (zv_request_t));
}
static void
-zvol_read(void *arg)
+zvol_discard_task(void *arg)
+{
+ zv_request_task_t *task = arg;
+ zvol_discard(&task->zvr);
+ zv_request_task_free(task);
+}
+
+static void
+zvol_read(zv_request_t *zvr)
{
- zv_request_t *zvr = arg;
struct bio *bio = zvr->bio;
int error = 0;
zfs_uio_t uio;
@@ -295,7 +325,14 @@ zvol_read(void *arg)
blk_generic_end_io_acct(q, disk, READ, bio, start_time);
BIO_END_IO(bio, -error);
- kmem_free(zvr, sizeof (zv_request_t));
+}
+
+static void
+zvol_read_task(void *arg)
+{
+ zv_request_task_t *task = arg;
+ zvol_read(&task->zvr);
+ zv_request_task_free(task);
}
#ifdef HAVE_SUBMIT_BIO_IN_BLOCK_DEVICE_OPERATIONS
@@ -318,7 +355,6 @@ zvol_request(struct request_queue *q, struct bio *bio)
uint64_t offset = BIO_BI_SECTOR(bio) << 9;
uint64_t size = BIO_BI_SIZE(bio);
int rw = bio_data_dir(bio);
- zv_request_t *zvr;
if (bio_has_data(bio) && offset + size > zv->zv_volsize) {
printk(KERN_INFO
@@ -331,6 +367,12 @@ zvol_request(struct request_queue *q, struct bio *bio)
goto out;
}
+ zv_request_t zvr = {
+ .zv = zv,
+ .bio = bio,
+ };
+ zv_request_task_t *task;
+
if (rw == WRITE) {
if (unlikely(zv->zv_flags & ZVOL_RDONLY)) {
BIO_END_IO(bio, -SET_ERROR(EROFS));
@@ -357,15 +399,13 @@ zvol_request(struct request_queue *q, struct bio *bio)
zv->zv_zilog = zil_open(zv->zv_objset,
zvol_get_data);
zv->zv_flags |= ZVOL_WRITTEN_TO;
+ /* replay / destroy done in zvol_create_minor */
+ VERIFY0((zv->zv_zilog->zl_header->zh_flags &
+ ZIL_REPLAY_NEEDED));
}
rw_downgrade(&zv->zv_suspend_lock);
}
- zvr = kmem_alloc(sizeof (zv_request_t), KM_SLEEP);
- zvr->zv = zv;
- zvr->bio = bio;
- taskq_init_ent(&zvr->ent);
-
/*
* We don't want this thread to be blocked waiting for i/o to
* complete, so we instead wait from a taskq callback. The
@@ -398,17 +438,19 @@ zvol_request(struct request_queue *q, struct bio *bio)
*/
if (bio_is_discard(bio) || bio_is_secure_erase(bio)) {
if (zvol_request_sync) {
- zvol_discard(zvr);
+ zvol_discard(&zvr);
} else {
+ task = zv_request_task_create(zvr);
taskq_dispatch_ent(zvol_taskq,
- zvol_discard, zvr, 0, &zvr->ent);
+ zvol_discard_task, task, 0, &task->ent);
}
} else {
if (zvol_request_sync) {
- zvol_write(zvr);
+ zvol_write(&zvr);
} else {
+ task = zv_request_task_create(zvr);
taskq_dispatch_ent(zvol_taskq,
- zvol_write, zvr, 0, &zvr->ent);
+ zvol_write_task, task, 0, &task->ent);
}
}
} else {
@@ -422,19 +464,15 @@ zvol_request(struct request_queue *q, struct bio *bio)
goto out;
}
- zvr = kmem_alloc(sizeof (zv_request_t), KM_SLEEP);
- zvr->zv = zv;
- zvr->bio = bio;
- taskq_init_ent(&zvr->ent);
-
rw_enter(&zv->zv_suspend_lock, RW_READER);
/* See comment in WRITE case above. */
if (zvol_request_sync) {
- zvol_read(zvr);
+ zvol_read(&zvr);
} else {
+ task = zv_request_task_create(zvr);
taskq_dispatch_ent(zvol_taskq,
- zvol_read, zvr, 0, &zvr->ent);
+ zvol_read_task, task, 0, &task->ent);
}
}
@@ -947,12 +985,16 @@ zvol_os_create_minor(const char *name)
blk_queue_flag_set(QUEUE_FLAG_SCSI_PASSTHROUGH, zv->zv_zso->zvo_queue);
#endif
+ ASSERT3P(zv->zv_zilog, ==, NULL);
+ zv->zv_zilog = zil_open(os, zvol_get_data);
if (spa_writeable(dmu_objset_spa(os))) {
if (zil_replay_disable)
- zil_destroy(dmu_objset_zil(os), B_FALSE);
+ zil_destroy(zv->zv_zilog, B_FALSE);
else
zil_replay(os, zv, zvol_replay_vector);
}
+ zil_close(zv->zv_zilog);
+ zv->zv_zilog = NULL;
ASSERT3P(zv->zv_kstat.dk_kstats, ==, NULL);
dataset_kstats_create(&zv->zv_kstat, zv->zv_objset);
diff --git a/sys/contrib/openzfs/module/zcommon/zfs_prop.c b/sys/contrib/openzfs/module/zcommon/zfs_prop.c
index b78331187e13..402d749c1aeb 100644
--- a/sys/contrib/openzfs/module/zcommon/zfs_prop.c
+++ b/sys/contrib/openzfs/module/zcommon/zfs_prop.c
@@ -417,7 +417,7 @@ zfs_prop_init(void)
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
"on | off | lzjb | gzip | gzip-[1-9] | zle | lz4 | "
"zstd | zstd-[1-19] | "
- "zstd-fast-[1-10,20,30,40,50,60,70,80,90,100,500,1000]",
+ "zstd-fast | zstd-fast-[1-10,20,30,40,50,60,70,80,90,100,500,1000]",
"COMPRESS", compress_table);
zprop_register_index(ZFS_PROP_SNAPDIR, "snapdir", ZFS_SNAPDIR_HIDDEN,
PROP_INHERIT, ZFS_TYPE_FILESYSTEM,
diff --git a/sys/contrib/openzfs/module/zfs/abd.c b/sys/contrib/openzfs/module/zfs/abd.c
index 7d3a2f6d69e2..1e6645c90c95 100644
--- a/sys/contrib/openzfs/module/zfs/abd.c
+++ b/sys/contrib/openzfs/module/zfs/abd.c
@@ -555,8 +555,12 @@ abd_get_offset_impl(abd_t *abd, abd_t *sabd, size_t off, size_t size)
abd_t *
abd_get_offset_struct(abd_t *abd, abd_t *sabd, size_t off, size_t size)
{
+ abd_t *result;
abd_init_struct(abd);
- return (abd_get_offset_impl(abd, sabd, off, size));
+ result = abd_get_offset_impl(abd, sabd, off, size);
+ if (result != abd)
+ abd_fini_struct(abd);
+ return (result);
}
abd_t *
diff --git a/sys/contrib/openzfs/module/zfs/spa_misc.c b/sys/contrib/openzfs/module/zfs/spa_misc.c
index 0dacf9027b27..1a2e5abc5335 100644
--- a/sys/contrib/openzfs/module/zfs/spa_misc.c
+++ b/sys/contrib/openzfs/module/zfs/spa_misc.c
@@ -2923,10 +2923,10 @@ ZFS_MODULE_PARAM(zfs, zfs_, recover, INT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs, zfs_, free_leak_on_eio, INT, ZMOD_RW,
"Set to ignore IO errors during free and permanently leak the space");
-ZFS_MODULE_PARAM(zfs, zfs_, deadman_checktime_ms, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_deadman, zfs_deadman_, checktime_ms, ULONG, ZMOD_RW,
"Dead I/O check interval in milliseconds");
-ZFS_MODULE_PARAM(zfs, zfs_, deadman_enabled, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_deadman, zfs_deadman_, enabled, INT, ZMOD_RW,
"Enable deadman timer");
ZFS_MODULE_PARAM(zfs_spa, spa_, asize_inflation, INT, ZMOD_RW,
diff --git a/sys/contrib/openzfs/module/zfs/zfs_vnops.c b/sys/contrib/openzfs/module/zfs/zfs_vnops.c
index a35c17f86f93..0af03e9233b3 100644
--- a/sys/contrib/openzfs/module/zfs/zfs_vnops.c
+++ b/sys/contrib/openzfs/module/zfs/zfs_vnops.c
@@ -350,9 +350,11 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
}
/*
- * If immutable or not appending then return EPERM
+ * If immutable or not appending then return EPERM.
+ * Intentionally allow ZFS_READONLY through here.
+ * See zfs_zaccess_common()
*/
- if ((zp->z_pflags & (ZFS_IMMUTABLE | ZFS_READONLY)) ||
+ if ((zp->z_pflags & ZFS_IMMUTABLE) ||
((zp->z_pflags & ZFS_APPENDONLY) && !(ioflag & O_APPEND) &&
(zfs_uio_offset(uio) < zp->z_size))) {
ZFS_EXIT(zfsvfs);
diff --git a/sys/contrib/openzfs/module/zfs/zvol.c b/sys/contrib/openzfs/module/zfs/zvol.c
index 7c6dae8650c7..44f9832ce857 100644
--- a/sys/contrib/openzfs/module/zfs/zvol.c
+++ b/sys/contrib/openzfs/module/zfs/zvol.c
@@ -473,7 +473,19 @@ zvol_replay_truncate(void *arg1, void *arg2, boolean_t byteswap)
offset = lr->lr_offset;
length = lr->lr_length;
- return (dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, offset, length));
+ dmu_tx_t *tx = dmu_tx_create(zv->zv_objset);
+ dmu_tx_mark_netfree(tx);
+ int error = dmu_tx_assign(tx, TXG_WAIT);
+ if (error != 0) {
+ dmu_tx_abort(tx);
+ } else {
+ zil_replaying(zv->zv_zilog, tx);
+ dmu_tx_commit(tx);
+ error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, offset,
+ length);
+ }
+
+ return (error);
}
/*
@@ -513,6 +525,7 @@ zvol_replay_write(void *arg1, void *arg2, boolean_t byteswap)
dmu_tx_abort(tx);
} else {
dmu_write(os, ZVOL_OBJ, offset, length, data, tx);
+ zil_replaying(zv->zv_zilog, tx);
dmu_tx_commit(tx);
}
diff --git a/sys/contrib/openzfs/tests/runfiles/common.run b/sys/contrib/openzfs/tests/runfiles/common.run
index fcb0fa6cd24f..895a5eeba324 100644
--- a/sys/contrib/openzfs/tests/runfiles/common.run
+++ b/sys/contrib/openzfs/tests/runfiles/common.run
@@ -398,6 +398,7 @@ tests = ['zpool_import_001_pos', 'zpool_import_002_pos',
'import_cachefile_device_replaced',
'import_cachefile_mirror_attached',
'import_cachefile_mirror_detached',
+ 'import_cachefile_paths_changed',
'import_cachefile_shared_device',
'import_devices_missing',
'import_paths_changed',
diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg b/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg
index a43ddd016fde..0db9724eead0 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg
+++ b/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg
@@ -33,6 +33,7 @@ export SYSTEM_FILES_COMMON='arp
du
echo
egrep
+ env
expr
false
file
@@ -117,7 +118,6 @@ export SYSTEM_FILES_FREEBSD='chflags
compress
diskinfo
dumpon
- env
fsck
getextattr
gpart
diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib b/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib
index d494eda5533f..bd77bae7d967 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib
+++ b/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib
@@ -41,7 +41,7 @@
# PATH may have been modified by sudo's secure_path behavior.
#
if [ -n "$STF_PATH" ]; then
- PATH="$STF_PATH"
+ export PATH="$STF_PATH"
fi
#
@@ -2766,10 +2766,6 @@ function add_user #<group_name> <user_name> <basedir>
;;
esac
- echo "export PATH=\"$STF_PATH\"" >>$basedir/$user/.profile
- echo "export PATH=\"$STF_PATH\"" >>$basedir/$user/.bash_profile
- echo "export PATH=\"$STF_PATH\"" >>$basedir/$user/.login
-
return 0
}
@@ -3393,8 +3389,17 @@ function user_run
typeset user=$1
shift
- log_note "user:$user $@"
- eval su - \$user -c \"$@\" > $TEST_BASE_DIR/out 2>$TEST_BASE_DIR/err
+ log_note "user: $user"
+ log_note "cmd: $*"
+
+ typeset out=$TEST_BASE_DIR/out
+ typeset err=$TEST_BASE_DIR/err
+
+ sudo -Eu $user env PATH="$PATH" ksh <<<"$*" >$out 2>$err
+ typeset res=$?
+ log_note "out: $(<$out)"
+ log_note "err: $(<$err)"
+ return $res
}
#
diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg b/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg
index e93e299ea25a..1cef60b0d634 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg
+++ b/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg
@@ -27,10 +27,10 @@ COMPRESSED_ARC_ENABLED compressed_arc_enabled zfs_compressed_arc_enabled
CONDENSE_INDIRECT_COMMIT_ENTRY_DELAY_MS condense.indirect_commit_entry_delay_ms zfs_condense_indirect_commit_entry_delay_ms
CONDENSE_MIN_MAPPING_BYTES condense.min_mapping_bytes zfs_condense_min_mapping_bytes
DBUF_CACHE_MAX_BYTES dbuf_cache.max_bytes dbuf_cache_max_bytes
-DEADMAN_CHECKTIME_MS deadman_checktime_ms zfs_deadman_checktime_ms
-DEADMAN_FAILMODE deadman_failmode zfs_deadman_failmode
-DEADMAN_SYNCTIME_MS deadman_synctime_ms zfs_deadman_synctime_ms
-DEADMAN_ZIOTIME_MS deadman_ziotime_ms zfs_deadman_ziotime_ms
+DEADMAN_CHECKTIME_MS deadman.checktime_ms zfs_deadman_checktime_ms
+DEADMAN_FAILMODE deadman.failmode zfs_deadman_failmode
+DEADMAN_SYNCTIME_MS deadman.synctime_ms zfs_deadman_synctime_ms
+DEADMAN_ZIOTIME_MS deadman.ziotime_ms zfs_deadman_ziotime_ms
DISABLE_IVSET_GUID_CHECK disable_ivset_guid_check zfs_disable_ivset_guid_check
INITIALIZE_CHUNK_SIZE initialize_chunk_size zfs_initialize_chunk_size
INITIALIZE_VALUE initialize_value zfs_initialize_value
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh
index 9440e807f206..caf8a9a2d0ee 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_002_pos.ksh
@@ -47,31 +47,32 @@ function cleanup
{
unset ZFS_ABORT
- if [[ -d $corepath ]]; then
- rm -rf $corepath
+ if is_freebsd && [ -n "$old_corefile" ]; then
+ sysctl kern.corefile=$old_corefile
fi
- if poolexists $pool; then
- log_must zpool destroy -f $pool
- fi
+ # Clean up the pool created if we failed to abort.
+ poolexists $pool && destroy_pool $pool
+
+ rm -rf $corepath $vdev1 $vdev2 $vdev3
}
log_assert "With ZFS_ABORT set, all zpool commands can abort and generate a core file."
log_onexit cleanup
-#preparation work for testing
corepath=$TESTDIR/core
+corefile=$corepath/zpool.core
if [[ -d $corepath ]]; then
- rm -rf $corepath
+ log_must rm -rf $corepath
fi
-mkdir $corepath
+log_must mkdir $corepath
pool=pool.$$
vdev1=$TESTDIR/file1
vdev2=$TESTDIR/file2
vdev3=$TESTDIR/file3
for vdev in $vdev1 $vdev2 $vdev3; do
- mkfile $MINVDEVSIZE $vdev
+ log_must mkfile $MINVDEVSIZE $vdev
done
set -A cmds "create $pool mirror $vdev1 $vdev2" "list $pool" "iostat $pool" \
@@ -86,27 +87,25 @@ set -A badparams "" "create" "destroy" "add" "remove" "list *" "iostat" "status"
"import" "export" "upgrade" "history -?" "get" "set"
if is_linux; then
- ulimit -c unlimited
- echo "$corepath/core.zpool" >/proc/sys/kernel/core_pattern
+ echo $corefile >/proc/sys/kernel/core_pattern
echo 0 >/proc/sys/kernel/core_uses_pid
- export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
elif is_freebsd; then
- ulimit -c unlimited
- log_must sysctl kern.corefile=$corepath/core.zpool
- export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
-else
- coreadm -p ${corepath}/core.%f
+ old_corefile=$(sysctl -n kern.corefile)
+ log_must sysctl kern.corefile=$corefile
fi
+ulimit -c unlimited
+export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
export ZFS_ABORT=yes
for subcmd in "${cmds[@]}" "${badparams[@]}"; do
- corefile=${corepath}/core.zpool
zpool $subcmd >/dev/null 2>&1
if [[ ! -e $corefile ]]; then
- log_fail "zpool $subcmd cannot generate core file with ZFS_ABORT set."
+ log_fail "zpool $subcmd cannot generate core file with ZFS_ABORT set."
fi
rm -f $corefile
done
+unset ZFS_ABORT
+
log_pass "With ZFS_ABORT set, zpool command can abort and generate core file as expected."
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh
index d51633745d76..71d73c0f80e5 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool/zpool_003_pos.ksh
@@ -44,9 +44,17 @@
function cleanup
{
+ unset ZFS_ABORT
+
if is_freebsd && [ -n "$old_corefile" ]; then
sysctl kern.corefile=$old_corefile
fi
+
+ rm -rf $corepath
+
+ # Don't leave the pool frozen.
+ destroy_pool $TESTPOOL
+ default_mirror_setup $DISKS
}
verify_runnable "both"
@@ -54,7 +62,14 @@ verify_runnable "both"
log_assert "Debugging features of zpool should succeed."
log_onexit cleanup
-log_must zpool -? > /dev/null 2>&1
+corepath=$TESTDIR/core
+corefile=$corepath/zpool.core
+if [[ -d $corepath ]]; then
+ log_must rm -rf $corepath
+fi
+log_must mkdir $corepath
+
+log_must eval "zpool -? >/dev/null 2>&1"
if is_global_zone ; then
log_must zpool freeze $TESTPOOL
@@ -65,26 +80,22 @@ fi
log_mustnot zpool freeze fakepool
-# Remove corefile possibly left by previous failing run of this test.
-[[ -f core ]] && log_must rm -f core
-
if is_linux; then
- ulimit -c unlimited
- echo "core" >/proc/sys/kernel/core_pattern
+ echo $corefile >/proc/sys/kernel/core_pattern
echo 0 >/proc/sys/kernel/core_uses_pid
- export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
elif is_freebsd; then
- ulimit -c unlimited
old_corefile=$(sysctl -n kern.corefile)
- log_must sysctl kern.corefile=core
- export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
+ log_must sysctl kern.corefile=$corefile
fi
+ulimit -c unlimited
+
+export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
+export ZFS_ABORT=yes
+
+zpool >/dev/null 2>&1
-ZFS_ABORT=1; export ZFS_ABORT
-zpool > /dev/null 2>&1
unset ZFS_ABORT
-[[ -f core ]] || log_fail "zpool did not dump core by request."
-[[ -f core ]] && log_must rm -f core
+[[ -f $corefile ]] || log_fail "zpool did not dump core by request."
log_pass "Debugging features of zpool succeed."
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_import/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_import/Makefile.am
index a99c5011e250..a8c9a31dcfdc 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_import/Makefile.am
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_import/Makefile.am
@@ -9,6 +9,7 @@ dist_pkgdata_SCRIPTS = \
import_cachefile_device_replaced.ksh \
import_cachefile_mirror_attached.ksh \
import_cachefile_mirror_detached.ksh \
+ import_cachefile_paths_changed.ksh \
import_cachefile_shared_device.ksh \
import_devices_missing.ksh \
import_paths_changed.ksh \
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_paths_changed.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_paths_changed.ksh
new file mode 100755
index 000000000000..0902bc49f4b1
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_paths_changed.ksh
@@ -0,0 +1,117 @@
+#!/bin/ksh -p
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2021 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
+
+#
+# DESCRIPTION:
+# A pool should be importable from a cachefile even if device paths
+# have changed.
+#
+# STRATEGY:
+# 1. Create a pool using a cachefile
+# 2. Backup cachefile
+# 3. Export the pool.
+# 4. Change the paths of some of the devices.
+# 5. Verify that we can import the pool using the cachefile.
+#
+
+verify_runnable "global"
+
+log_onexit cleanup
+
+function test_new_paths
+{
+ typeset poolcreate="$1"
+ typeset pathstochange="$2"
+
+ log_note "$0: pool '$poolcreate', changing paths of $pathstochange."
+
+ log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate
+
+ log_must cp $CPATH $CPATHBKP
+
+ log_must zpool export $TESTPOOL1
+
+ for dev in $pathstochange; do
+ log_must mv $dev "${dev}_new"
+ done
+
+ log_must zpool import -c $CPATHBKP $TESTPOOL1
+ log_must check_pool_healthy $TESTPOOL1
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+ log_must rm -f $CPATH $CPATHBKP
+ for dev in $pathstochange; do
+ log_must mv "${dev}_new" $dev
+ done
+
+ log_note ""
+}
+
+function test_duplicate_pools
+{
+ typeset poolcreate="$1"
+ typeset pathstocopy="$2"
+
+ log_note "$0: pool '$poolcreate', creating duplicate pool using $pathstocopy."
+
+ log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate
+ log_must zpool export $TESTPOOL1
+
+ for dev in $pathstocopy; do
+ log_must cp $dev "${dev}_orig"
+
+ done
+
+ log_must zpool create -f -o cachefile=$CPATH $TESTPOOL1 $poolcreate
+ log_must cp $CPATH $CPATHBKP
+ log_must zpool export $TESTPOOL1
+
+ for dev in $pathstocopy; do
+ log_must mv $dev "${dev}_new"
+ done
+
+ log_must zpool import -c $CPATHBKP
+ log_must zpool import -c $CPATHBKP $TESTPOOL1
+ log_must check_pool_healthy $TESTPOOL1
+
+ # Cleanup
+ log_must zpool destroy $TESTPOOL1
+ log_must rm -f $CPATH $CPATHBKP
+ for dev in $pathstocopy; do
+ log_must rm "${dev}_orig"
+ log_must mv "${dev}_new" $dev
+ done
+
+ log_note ""
+}
+
+test_new_paths "$VDEV0 $VDEV1" "$VDEV0 $VDEV1"
+test_new_paths "mirror $VDEV0 $VDEV1" "$VDEV0 $VDEV1"
+test_new_paths "$VDEV0 log $VDEV1" "$VDEV0 $VDEV1"
+test_new_paths "raidz $VDEV0 $VDEV1 $VDEV2" "$VDEV0 $VDEV1 $VDEV2"
+test_new_paths "draid $VDEV0 $VDEV1 $VDEV2" "$VDEV0 $VDEV1 $VDEV2"
+
+test_duplicate_pools "$VDEV0 $VDEV1" "$VDEV0 $VDEV1"
+test_duplicate_pools "mirror $VDEV0 $VDEV1" "$VDEV0 $VDEV1"
+test_duplicate_pools "$VDEV0 log $VDEV1" "$VDEV0 $VDEV1"
+test_duplicate_pools "raidz $VDEV0 $VDEV1 $VDEV2" "$VDEV0 $VDEV1 $VDEV2"
+test_duplicate_pools "draid $VDEV0 $VDEV1 $VDEV2" "$VDEV0 $VDEV1 $VDEV2"
+
+log_pass "zpool import with cachefile succeeded after changing device paths."
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/events_002_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/events_002_pos.ksh
index 7a78d93a8438..586eaa9e1fd8 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/events_002_pos.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/events_002_pos.ksh
@@ -66,7 +66,7 @@ log_must zpool create $MPOOL mirror $VDEV1 $VDEV2
# 2. Start the ZED and verify it handles missed events.
log_must zed_start
-log_must file_wait $ZED_DEBUG_LOG
+log_must file_wait_event $ZED_DEBUG_LOG 'sysevent\.fs\.zfs\.config_sync' 150
log_must cp $ZED_DEBUG_LOG $TMP_EVENTS_ZED
awk -v event="sysevent.fs.zfs.pool_create" \
@@ -92,12 +92,11 @@ done
# 5. Start the ZED and verify it only handled the new missed events.
log_must zed_start
-log_must file_wait $ZED_DEBUG_LOG 35
+log_must file_wait_event $ZED_DEBUG_LOG 'sysevent\.fs\.zfs\.resilver_finish' 150
log_must cp $ZED_DEBUG_LOG $TMP_EVENTS_ZED
-log_mustnot grep -q "sysevent.fs.zfs.pool_create" $TMP_EVENTS_ZED
+log_mustnot file_wait_event $ZED_DEBUG_LOG 'sysevent\.fs\.zfs\.pool_create' 30
log_must grep -q "sysevent.fs.zfs.vdev_online" $TMP_EVENTS_ZED
log_must grep -q "sysevent.fs.zfs.resilver_start" $TMP_EVENTS_ZED
-log_must grep -q "sysevent.fs.zfs.resilver_finish" $TMP_EVENTS_ZED
log_pass "Verify ZED handles missed events on when starting"
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/xattr/xattr_003_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/xattr/xattr_003_neg.ksh
index a3b25ff66266..ba27d043b7fe 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/xattr/xattr_003_neg.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/xattr/xattr_003_neg.ksh
@@ -43,34 +43,40 @@
# 4. Check that we're unable to write an xattr as a non-root user
#
-function cleanup {
-
- log_must rm $TESTDIR/myfile.$$
-
+function cleanup
+{
+ rm -f $testfile $tempfile
}
log_assert "read/write xattr on a file with no permissions fails"
log_onexit cleanup
-log_must touch $TESTDIR/myfile.$$
-create_xattr $TESTDIR/myfile.$$ passwd /etc/passwd
+typeset testfile=$TESTDIR/testfile.$$
+typeset tempfile=/tmp/tempfile.$$
+
+log_must touch $testfile
+create_xattr $testfile passwd /etc/passwd
-log_must chmod 000 $TESTDIR/myfile.$$
+log_must chmod 000 $testfile
if is_illumos; then
- log_mustnot su $ZFS_USER -c "runat $TESTDIR/myfile.$$ cat passwd"
- log_mustnot su $ZFS_USER -c "runat $TESTDIR/myfile.$$ cp /etc/passwd ."
+ log_mustnot su $ZFS_USER -c "runat $testfile cat passwd"
+ log_mustnot su $ZFS_USER -c "runat $testfile cp /etc/passwd ."
else
- user_run $ZFS_USER eval \
- "get_xattr passwd $TESTDIR/myfile.$$ >/tmp/passwd.$$"
- log_mustnot diff /etc/passwd /tmp/passwd.$$
- log_must rm /tmp/passwd.$$
+ log_mustnot user_run $ZFS_USER "
+. $STF_SUITE/include/libtest.shlib
+get_xattr passwd $testfile >$tempfile
+"
+ log_mustnot diff -q /etc/passwd $tempfile
+ log_must rm $tempfile
- user_run $ZFS_USER eval \
- "set_xattr_stdin passwd $TESTDIR/myfile.$$ </etc/group"
- log_must chmod 644 $TESTDIR/myfile.$$
- get_xattr passwd $TESTDIR/myfile.$$ >/tmp/passwd.$$
- log_must diff /etc/passwd /tmp/passwd.$$
- log_must rm /tmp/passwd.$$
+ log_mustnot user_run $ZFS_USER "
+. $STF_SUITE/include/libtest.shlib
+set_xattr_stdin passwd $testfile </etc/group
+"
+ log_must chmod 644 $testfile
+ get_xattr passwd $testfile >$tempfile
+ log_must diff -q /etc/passwd $tempfile
+ log_must rm $tempfile
fi
log_pass "read/write xattr on a file with no permissions fails"
diff --git a/sys/modules/zfs/zfs_config.h b/sys/modules/zfs/zfs_config.h
index ae5316a46f10..f5a7ab069879 100644
--- a/sys/modules/zfs/zfs_config.h
+++ b/sys/modules/zfs/zfs_config.h
@@ -734,7 +734,7 @@
/* #undef ZFS_IS_GPL_COMPATIBLE */
/* Define the project alias string. */
-#define ZFS_META_ALIAS "zfs-2.0.0-FreeBSD_gbedbc13da"
+#define ZFS_META_ALIAS "zfs-2.0.0-FreeBSD_g9305ff2ed"
/* Define the project author. */
#define ZFS_META_AUTHOR "OpenZFS"
@@ -764,7 +764,7 @@
#define ZFS_META_NAME "zfs"
/* Define the project release. */
-#define ZFS_META_RELEASE "FreeBSD_gbedbc13da"
+#define ZFS_META_RELEASE "FreeBSD_g9305ff2ed"
/* Define the project version. */
#define ZFS_META_VERSION "2.0.0"