diff options
| author | Martin Matuska <mm@FreeBSD.org> | 2021-03-14 01:23:51 +0000 |
|---|---|---|
| committer | Martin Matuska <mm@FreeBSD.org> | 2021-04-04 13:18:45 +0000 |
| commit | cf2a72643460a2bb50fcdf78fb8721a692315793 (patch) | |
| tree | efa442c1e0902d1e9b49d7e8503d5feb675bfedf | |
| parent | 1260724822b5830411cbf56d48e997be1628e53b (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)
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" |
