diff --git a/.github/workflows/checkstyle.yaml b/.github/workflows/checkstyle.yaml index b5bdfac168a6..61b4c480ca22 100644 --- a/.github/workflows/checkstyle.yaml +++ b/.github/workflows/checkstyle.yaml @@ -19,7 +19,7 @@ jobs: if: ${{ needs.skip-checkstyle.outputs.should_skip != 'true' }} runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install dependencies @@ -54,7 +54,7 @@ jobs: if: failure() && steps.CheckABI.outcome == 'failure' run: | find -name *.abi | tar -cf abi_files.tar -T - - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: failure() && steps.CheckABI.outcome == 'failure' with: name: New ABI files (use only if you're sure about interface changes) diff --git a/.github/workflows/zfs-tests-functional.yml b/.github/workflows/zfs-tests-functional.yml index 119deee8fcd6..beb8aaf6a69b 100644 --- a/.github/workflows/zfs-tests-functional.yml +++ b/.github/workflows/zfs-tests-functional.yml @@ -23,7 +23,7 @@ jobs: os: [18.04, 20.04] runs-on: ubuntu-${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install dependencies @@ -86,7 +86,7 @@ jobs: sudo chmod +r $RESULTS_PATH/* # Replace ':' in dir names, actions/upload-artifact doesn't support it for f in $(find /var/tmp/test_results -name '*:*'); do mv "$f" "${f//:/__}"; done - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: failure() with: name: Test logs Ubuntu-${{ matrix.os }} diff --git a/.github/workflows/zfs-tests-sanity.yml b/.github/workflows/zfs-tests-sanity.yml index 2b2022f83cc1..22059130ff66 100644 --- a/.github/workflows/zfs-tests-sanity.yml +++ b/.github/workflows/zfs-tests-sanity.yml @@ -15,11 +15,9 @@ jobs: concurrent_skipping: 'same_content_newer' tests: - needs: skip-tests-sanity - if: ${{ needs.skip-tests-sanity.outputs.should_skip != 'true' }} - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install dependencies @@ -82,7 +80,7 @@ jobs: sudo chmod +r $RESULTS_PATH/* # Replace ':' in dir names, actions/upload-artifact doesn't support it for f in $(find /var/tmp/test_results -name '*:*'); do mv "$f" "${f//:/__}"; done - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: failure() with: name: Test logs diff --git a/.github/workflows/zloop.yml b/.github/workflows/zloop.yml index 75fc95ac7d8d..59425232d51b 100644 --- a/.github/workflows/zloop.yml +++ b/.github/workflows/zloop.yml @@ -15,13 +15,11 @@ jobs: concurrent_skipping: 'same_content_newer' tests: - needs: skip-zloop - if: ${{ needs.skip-zloop.outputs.should_skip != 'true' }} - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 env: TEST_DIR: /var/tmp/zloop steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install dependencies @@ -61,7 +59,7 @@ jobs: if: failure() run: | sudo chmod +r -R $TEST_DIR/ - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: failure() with: name: Logs @@ -69,7 +67,7 @@ jobs: /var/tmp/zloop/*/ !/var/tmp/zloop/*/vdev/ if-no-files-found: ignore - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: failure() with: name: Pool files diff --git a/META b/META index 7dd5b311d0c2..7879ff1d0abf 100644 --- a/META +++ b/META @@ -1,10 +1,10 @@ Meta: 1 Name: zfs Branch: 1.0 -Version: 2.1.6 +Version: 2.1.7 Release: 1 Release-Tags: relext License: CDDL Author: OpenZFS -Linux-Maximum: 5.19 +Linux-Maximum: 6.0 Linux-Minimum: 3.10 diff --git a/cmd/arc_summary/arc_summary3 b/cmd/arc_summary/arc_summary3 index 7b28012ede4d..301c485b34ba 100755 --- a/cmd/arc_summary/arc_summary3 +++ b/cmd/arc_summary/arc_summary3 @@ -686,9 +686,9 @@ def section_archits(kstats_dict): print() print('Cache hits by data type:') dt_todo = (('Demand data:', arc_stats['demand_data_hits']), - ('Demand prefetch data:', arc_stats['prefetch_data_hits']), + ('Prefetch data:', arc_stats['prefetch_data_hits']), ('Demand metadata:', arc_stats['demand_metadata_hits']), - ('Demand prefetch metadata:', + ('Prefetch metadata:', arc_stats['prefetch_metadata_hits'])) for title, value in dt_todo: @@ -697,10 +697,10 @@ def section_archits(kstats_dict): print() print('Cache misses by data type:') dm_todo = (('Demand data:', arc_stats['demand_data_misses']), - ('Demand prefetch data:', + ('Prefetch data:', arc_stats['prefetch_data_misses']), ('Demand metadata:', arc_stats['demand_metadata_misses']), - ('Demand prefetch metadata:', + ('Prefetch metadata:', arc_stats['prefetch_metadata_misses'])) for title, value in dm_todo: diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index 7646d899ef20..7c719f07db03 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -2995,7 +2995,7 @@ open_objset(const char *path, void *tag, objset_t **osp) } sa_os = *osp; - return (0); + return (err); } static void diff --git a/cmd/zed/agents/fmd_api.c b/cmd/zed/agents/fmd_api.c index 607b387ca3a8..f6cb7635f030 100644 --- a/cmd/zed/agents/fmd_api.c +++ b/cmd/zed/agents/fmd_api.c @@ -599,6 +599,7 @@ fmd_timer_install(fmd_hdl_t *hdl, void *arg, fmd_event_t *ep, hrtime_t delta) sev.sigev_notify_function = _timer_notify; sev.sigev_notify_attributes = NULL; sev.sigev_value.sival_ptr = ftp; + sev.sigev_signo = 0; timer_create(CLOCK_REALTIME, &sev, &ftp->ft_tid); timer_settime(ftp->ft_tid, 0, &its, NULL); diff --git a/cmd/zed/agents/zfs_mod.c b/cmd/zed/agents/zfs_mod.c index 27baed3936eb..a295f01f26b4 100644 --- a/cmd/zed/agents/zfs_mod.c +++ b/cmd/zed/agents/zfs_mod.c @@ -968,7 +968,7 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data) nvlist_t *tgt; int error; - char *tmp_devname, devname[MAXPATHLEN]; + char *tmp_devname, devname[MAXPATHLEN] = ""; uint64_t guid; if (nvlist_lookup_uint64(udev_nvl, ZFS_EV_VDEV_GUID, &guid) == 0) { @@ -1126,6 +1126,7 @@ zfs_deliver_dle(nvlist_t *nvl) strlcpy(name, devname, MAXPATHLEN); zfs_append_partition(name, MAXPATHLEN); } else { + sprintf(name, "unknown"); zed_log_msg(LOG_INFO, "zfs_deliver_dle: no guid or physpath"); } @@ -1215,7 +1216,7 @@ zfs_enum_pools(void *arg) * For now, each agent has its own libzfs instance */ int -zfs_slm_init() +zfs_slm_init(void) { if ((g_zfshdl = libzfs_init()) == NULL) return (-1); @@ -1241,7 +1242,7 @@ zfs_slm_init() } void -zfs_slm_fini() +zfs_slm_fini(void) { unavailpool_t *pool; pendingdev_t *device; diff --git a/cmd/zed/zed_disk_event.c b/cmd/zed/zed_disk_event.c index e31ec4cfc7e7..3c8e2fb38c15 100644 --- a/cmd/zed/zed_disk_event.c +++ b/cmd/zed/zed_disk_event.c @@ -402,7 +402,7 @@ zed_udev_monitor(void *arg) } int -zed_disk_event_init() +zed_disk_event_init(void) { int fd, fflags; @@ -438,7 +438,7 @@ zed_disk_event_init() } void -zed_disk_event_fini() +zed_disk_event_fini(void) { /* cancel monitor thread at recvmsg() */ (void) pthread_cancel(g_mon_tid); @@ -456,13 +456,13 @@ zed_disk_event_fini() #include "zed_disk_event.h" int -zed_disk_event_init() +zed_disk_event_init(void) { return (0); } void -zed_disk_event_fini() +zed_disk_event_fini(void) { } diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index f620e3729304..c827875f9995 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -8543,7 +8543,7 @@ static int zfs_do_wait(int argc, char **argv) { boolean_t enabled[ZFS_WAIT_NUM_ACTIVITIES]; - int error, i; + int error = 0, i; int c; /* By default, wait for all types of activity. */ diff --git a/cmd/zstream/zstream_dump.c b/cmd/zstream/zstream_dump.c index 04a4986b45d8..f0e83fb19da3 100644 --- a/cmd/zstream/zstream_dump.c +++ b/cmd/zstream/zstream_dump.c @@ -363,9 +363,6 @@ zstream_do_dump(int argc, char *argv[]) BSWAP_64(drrb->drr_fromguid); } - featureflags = - DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo); - (void) printf("BEGIN record\n"); (void) printf("\thdrtype = %lld\n", DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo)); @@ -465,6 +462,9 @@ zstream_do_dump(int argc, char *argv[]) BSWAP_64(drro->drr_maxblkid); } + featureflags = + DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo); + if (featureflags & DMU_BACKUP_FEATURE_RAW && drro->drr_bonuslen > drro->drr_raw_bonuslen) { (void) fprintf(stderr, diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c index ae72475e14b7..5e4c33615e2b 100644 --- a/cmd/ztest/ztest.c +++ b/cmd/ztest/ztest.c @@ -2193,6 +2193,7 @@ ztest_replay_write(void *arg1, void *arg2, boolean_t byteswap) * but not always, because we also want to verify correct * behavior when the data was not recently read into cache. */ + ASSERT(doi.doi_data_block_size); ASSERT0(offset % doi.doi_data_block_size); if (ztest_random(4) != 0) { int prefetch = ztest_random(2) ? diff --git a/cmd/zvol_wait/zvol_wait b/cmd/zvol_wait/zvol_wait index f1fa42e27dc9..0b2a8a3e60c3 100755 --- a/cmd/zvol_wait/zvol_wait +++ b/cmd/zvol_wait/zvol_wait @@ -109,6 +109,13 @@ while [ "$outer_loop" -lt 20 ]; do exit 0 fi fi + + # + # zvol_count made some progress - let's stay in this loop. + # + if [ "$old_zvols_count" -gt "$zvols_count" ]; then + outer_loop=$((outer_loop - 1)) + fi done echo "Timed out waiting on zvol links" diff --git a/config/always-pyzfs.m4 b/config/always-pyzfs.m4 index 00e5d0e2cbbd..efea49f5f025 100644 --- a/config/always-pyzfs.m4 +++ b/config/always-pyzfs.m4 @@ -46,6 +46,16 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [ ]) AC_SUBST(DEFINE_PYZFS) + dnl # + dnl # Autodetection disables pyzfs if kernel or srpm config + dnl # + AS_IF([test "x$enable_pyzfs" = xcheck], [ + AS_IF([test "x$ZFS_CONFIG" = xkernel -o "x$ZFS_CONFIG" = xsrpm ], [ + enable_pyzfs=no + AC_MSG_NOTICE([Disabling pyzfs for kernel/srpm config]) + ]) + ]) + dnl # dnl # Python "packaging" (or, failing that, "distlib") module is required to build and install pyzfs dnl # diff --git a/config/kernel-add-disk.m4 b/config/kernel-add-disk.m4 index 44a8a5fd25b6..86d81ea325b9 100644 --- a/config/kernel-add-disk.m4 +++ b/config/kernel-add-disk.m4 @@ -7,8 +7,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_ADD_DISK], [ #include ], [ struct gendisk *disk = NULL; - int err = add_disk(disk); - err = err; + int error __attribute__ ((unused)) = add_disk(disk); ]) ]) diff --git a/config/kernel-mod-param.m4 b/config/kernel-mod-param.m4 deleted file mode 100644 index e00f19d61e7d..000000000000 --- a/config/kernel-mod-param.m4 +++ /dev/null @@ -1,33 +0,0 @@ -dnl # -dnl # Grsecurity kernel API change -dnl # constified parameters of module_param_call() methods -dnl # -AC_DEFUN([ZFS_AC_KERNEL_SRC_MODULE_PARAM_CALL_CONST], [ - ZFS_LINUX_TEST_SRC([module_param_call], [ - #include - #include - - int param_get(char *b, const struct kernel_param *kp) - { - return (0); - } - - int param_set(const char *b, const struct kernel_param *kp) - { - return (0); - } - - module_param_call(p, param_set, param_get, NULL, 0644); - ],[]) -]) - -AC_DEFUN([ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST], [ - AC_MSG_CHECKING([whether module_param_call() is hardened]) - ZFS_LINUX_TEST_RESULT([module_param_call], [ - AC_MSG_RESULT(yes) - AC_DEFINE(MODULE_PARAM_CALL_CONST, 1, - [hardened module_param_call]) - ],[ - AC_MSG_RESULT(no) - ]) -]) diff --git a/config/kernel.m4 b/config/kernel.m4 index edcb70cbd64b..a3e6e4dc9519 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -121,7 +121,6 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ ZFS_AC_KERNEL_SRC_FMODE_T ZFS_AC_KERNEL_SRC_KUIDGID_T ZFS_AC_KERNEL_SRC_KUID_HELPERS - ZFS_AC_KERNEL_SRC_MODULE_PARAM_CALL_CONST ZFS_AC_KERNEL_SRC_RENAME ZFS_AC_KERNEL_SRC_CURRENT_TIME ZFS_AC_KERNEL_SRC_USERNS_CAPABILITIES @@ -240,7 +239,6 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ ZFS_AC_KERNEL_FMODE_T ZFS_AC_KERNEL_KUIDGID_T ZFS_AC_KERNEL_KUID_HELPERS - ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST ZFS_AC_KERNEL_RENAME ZFS_AC_KERNEL_CURRENT_TIME ZFS_AC_KERNEL_USERNS_CAPABILITIES @@ -938,8 +936,15 @@ dnl # like ZFS_LINUX_TRY_COMPILE, except the contents conftest.h are dnl # provided via the fifth parameter dnl # AC_DEFUN([ZFS_LINUX_TRY_COMPILE_HEADER], [ - ZFS_LINUX_COMPILE_IFELSE( - [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]], [[ZFS_META_LICENSE]])], - [test -f build/conftest/conftest.ko], - [$3], [$4], [$5]) + AS_IF([test "x$enable_linux_builtin" = "xyes"], [ + ZFS_LINUX_COMPILE_IFELSE( + [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]], + [[ZFS_META_LICENSE]])], + [test -f build/conftest/conftest.o], [$3], [$4], [$5]) + ], [ + ZFS_LINUX_COMPILE_IFELSE( + [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]], + [[ZFS_META_LICENSE]])], + [test -f build/conftest/conftest.ko], [$3], [$4], [$5]) + ]) ]) diff --git a/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in b/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in index b4f5707516ce..a29cf3a3dd81 100644 --- a/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in +++ b/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in @@ -8,5 +8,5 @@ ConditionKernelCommandLine=bootfs.rollback [Service] Type=oneshot -ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS" SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "$root@${SNAPNAME:-%v}"' +ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS"; SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "$root@${SNAPNAME:-%v}"' RemainAfterExit=yes diff --git a/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in b/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in index 28a4edc844ad..9e73d1a78724 100644 --- a/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in +++ b/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in @@ -8,5 +8,5 @@ ConditionKernelCommandLine=bootfs.snapshot [Service] Type=oneshot --ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS" SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$root@${SNAPNAME:-%v}"' +ExecStart=-/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS"; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$root@${SNAPNAME:-%v}"' RemainAfterExit=yes diff --git a/contrib/initramfs/scripts/zfs b/contrib/initramfs/scripts/zfs index 733c63ba5b4a..bc9211b24bee 100644 --- a/contrib/initramfs/scripts/zfs +++ b/contrib/initramfs/scripts/zfs @@ -327,7 +327,7 @@ mount_fs() # Need the _original_ datasets mountpoint! mountpoint=$(get_fs_value "$fs" mountpoint) - ZFS_CMD="mount -o zfsutil -t zfs" + ZFS_CMD="mount.zfs -o zfsutil" if [ "$mountpoint" = "legacy" ] || [ "$mountpoint" = "none" ]; then # Can't use the mountpoint property. Might be one of our # clones. Check the 'org.zol:mountpoint' property set in @@ -350,7 +350,7 @@ mount_fs() # If it's not a legacy filesystem, it can only be a # native one... if [ "$mountpoint" = "legacy" ]; then - ZFS_CMD="mount -t zfs" + ZFS_CMD="mount.zfs" fi fi @@ -916,7 +916,7 @@ mountroot() echo " not specified on the kernel command line." echo "" echo "Manually mount the root filesystem on $rootmnt and then exit." - echo "Hint: Try: mount -o zfsutil -t zfs ${ZFS_RPOOL-rpool}/ROOT/system $rootmnt" + echo "Hint: Try: mount.zfs -o zfsutil ${ZFS_RPOOL-rpool}/ROOT/system $rootmnt" shell fi diff --git a/contrib/pam_zfs_key/pam_zfs_key.c b/contrib/pam_zfs_key/pam_zfs_key.c index 0856c7534f0d..0db119382e7b 100644 --- a/contrib/pam_zfs_key/pam_zfs_key.c +++ b/contrib/pam_zfs_key/pam_zfs_key.c @@ -496,7 +496,6 @@ zfs_key_config_get_dataset(zfs_key_config_t *config) if (zhp == NULL) { pam_syslog(NULL, LOG_ERR, "dataset %s not found", config->homes_prefix); - zfs_close(zhp); return (NULL); } @@ -508,6 +507,10 @@ zfs_key_config_get_dataset(zfs_key_config_t *config) return (dsname); } + if (config->homes_prefix == NULL) { + return (NULL); + } + size_t len = ZFS_MAX_DATASET_NAME_LEN; size_t total_len = strlen(config->homes_prefix) + 1 + strlen(config->username); @@ -711,7 +714,10 @@ pam_sm_open_session(pam_handle_t *pamh, int flags, return (PAM_SUCCESS); } zfs_key_config_t config; - zfs_key_config_load(pamh, &config, argc, argv); + if (zfs_key_config_load(pamh, &config, argc, argv) != 0) { + return (PAM_SESSION_ERR); + } + if (config.uid < 1000) { zfs_key_config_free(&config); return (PAM_SUCCESS); @@ -765,7 +771,9 @@ pam_sm_close_session(pam_handle_t *pamh, int flags, return (PAM_SUCCESS); } zfs_key_config_t config; - zfs_key_config_load(pamh, &config, argc, argv); + if (zfs_key_config_load(pamh, &config, argc, argv) != 0) { + return (PAM_SESSION_ERR); + } if (config.uid < 1000) { zfs_key_config_free(&config); return (PAM_SUCCESS); diff --git a/contrib/truenas/changelog b/contrib/truenas/changelog index a426dbae76eb..79177c41f390 100644 --- a/contrib/truenas/changelog +++ b/contrib/truenas/changelog @@ -1,3 +1,17 @@ +openzfs (2.1.7-0) unstable; urgency=medium + + * Merge tag zfs-2.1.7 + * Expose libzutil error info in libpc_handle_t + * Build packages with debug symbols + * Add support for overlayfs for docker + * Optimize microzaps + * zed: Avoid core dump if wholedisk property does not exist + * zed: post a udev change event from spa_vdev_attach() + * SCALE: ignore wholedisk + * Skip trivial permission checks on xattrs for POSIX ACL type + + -- Ryan Moeller Wed, 07 Dec 2022 16:00:00 -0500 + openzfs (2.1.6-0) unstable; urgency=medium * Merge tag zfs-2.1.6 diff --git a/etc/systemd/system/Makefile.am b/etc/systemd/system/Makefile.am index 5e65e1db420c..35f833de5cbc 100644 --- a/etc/systemd/system/Makefile.am +++ b/etc/systemd/system/Makefile.am @@ -22,3 +22,4 @@ SUBSTFILES += $(systemdpreset_DATA) $(systemdunit_DATA) install-data-hook: $(MKDIR_P) "$(DESTDIR)$(systemdunitdir)" ln -sf /dev/null "$(DESTDIR)$(systemdunitdir)/zfs-import.service" + ln -sf /dev/null "$(DESTDIR)$(systemdunitdir)/zfs-load-key.service" diff --git a/etc/systemd/system/zfs-import-cache.service.in b/etc/systemd/system/zfs-import-cache.service.in index 5e5c6281c9d7..e841ca5596c2 100644 --- a/etc/systemd/system/zfs-import-cache.service.in +++ b/etc/systemd/system/zfs-import-cache.service.in @@ -5,7 +5,7 @@ DefaultDependencies=no Requires=systemd-udev-settle.service After=systemd-udev-settle.service After=cryptsetup.target -After=multipathd.target +After=multipathd.service After=systemd-remount-fs.service Before=zfs-import.target ConditionFileNotEmpty=@sysconfdir@/zfs/zpool.cache diff --git a/etc/systemd/system/zfs-import-scan.service.in b/etc/systemd/system/zfs-import-scan.service.in index d3c083f7e9cf..598ef501baa6 100644 --- a/etc/systemd/system/zfs-import-scan.service.in +++ b/etc/systemd/system/zfs-import-scan.service.in @@ -5,7 +5,7 @@ DefaultDependencies=no Requires=systemd-udev-settle.service After=systemd-udev-settle.service After=cryptsetup.target -After=multipathd.target +After=multipathd.service Before=zfs-import.target ConditionFileNotEmpty=!@sysconfdir@/zfs/zpool.cache ConditionPathIsDirectory=/sys/module/zfs diff --git a/include/libzfs.h b/include/libzfs.h index 4ee68ffab1ce..660c74e61155 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -150,6 +150,7 @@ typedef enum zfs_error { EZFS_NO_RESILVER_DEFER, /* pool doesn't support resilver_defer */ EZFS_EXPORT_IN_PROGRESS, /* currently exporting the pool */ EZFS_REBUILDING, /* resilvering (sequential reconstrution) */ + EZFS_CKSUM, /* insufficient replicas */ EZFS_UNKNOWN } zfs_error_t; @@ -257,10 +258,10 @@ extern int zpool_add(zpool_handle_t *, nvlist_t *); typedef struct splitflags { /* do not split, but return the config that would be split off */ - int dryrun : 1; + unsigned int dryrun : 1; /* after splitting, import the pool */ - int import : 1; + unsigned int import : 1; int name_flags; } splitflags_t; @@ -650,13 +651,13 @@ extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *, boolean_t); typedef struct renameflags { /* recursive rename */ - int recursive : 1; + unsigned int recursive : 1; /* don't unmount file systems */ - int nounmount : 1; + unsigned int nounmount : 1; /* force unmount file systems */ - int forceunmount : 1; + unsigned int forceunmount : 1; } renameflags_t; extern int zfs_rename(zfs_handle_t *, const char *, renameflags_t); diff --git a/include/os/freebsd/linux/compiler.h b/include/os/freebsd/linux/compiler.h index 20903717b58d..79f9b2d8a96a 100644 --- a/include/os/freebsd/linux/compiler.h +++ b/include/os/freebsd/linux/compiler.h @@ -83,7 +83,6 @@ #define __printf(a, b) __printflike(a, b) #define barrier() __asm__ __volatile__("": : :"memory") -#define smp_rmb() rmb() #define ___PASTE(a, b) a##b #define __PASTE(a, b) ___PASTE(a, b) diff --git a/include/os/freebsd/spl/sys/atomic.h b/include/os/freebsd/spl/sys/atomic.h index 1a68bfc4de23..01b13fc9afd7 100644 --- a/include/os/freebsd/spl/sys/atomic.h +++ b/include/os/freebsd/spl/sys/atomic.h @@ -57,7 +57,8 @@ extern uint64_t atomic_cas_64(volatile uint64_t *target, uint64_t cmp, uint64_t newval); #endif -#define membar_producer atomic_thread_fence_rel +#define membar_consumer() atomic_thread_fence_acq() +#define membar_producer() atomic_thread_fence_rel() static __inline uint32_t atomic_add_32_nv(volatile uint32_t *target, int32_t delta) diff --git a/include/os/freebsd/spl/sys/vnode.h b/include/os/freebsd/spl/sys/vnode.h index bcfc177a4751..b7ac12f3d676 100644 --- a/include/os/freebsd/spl/sys/vnode.h +++ b/include/os/freebsd/spl/sys/vnode.h @@ -95,9 +95,11 @@ vn_flush_cached_data(vnode_t *vp, boolean_t sync) if (vp->v_object->flags & OBJ_MIGHTBEDIRTY) { #endif int flags = sync ? OBJPC_SYNC : 0; + vn_lock(vp, LK_SHARED | LK_RETRY); zfs_vmobject_wlock(vp->v_object); vm_object_page_clean(vp->v_object, 0, 0, flags); zfs_vmobject_wunlock(vp->v_object); + VOP_UNLOCK(vp); } } diff --git a/include/os/linux/kernel/linux/mod_compat.h b/include/os/linux/kernel/linux/mod_compat.h index cc42c3f7c743..642ff9826b26 100644 --- a/include/os/linux/kernel/linux/mod_compat.h +++ b/include/os/linux/kernel/linux/mod_compat.h @@ -30,12 +30,16 @@ #include #include -/* Grsecurity kernel API change */ -#ifdef MODULE_PARAM_CALL_CONST +/* + * Despite constifying struct kernel_param_ops, some older kernels define a + * `__check_old_set_param()` function in their headers that checks for a + * non-constified `->set()`. This has long been fixed in Linux mainline, but + * since we support older kernels, we workaround it by using a preprocessor + * definition to disable it. + */ +#define __check_old_set_param(_) (0) + typedef const struct kernel_param zfs_kernel_param_t; -#else -typedef struct kernel_param zfs_kernel_param_t; -#endif #define ZMOD_RW 0644 #define ZMOD_RD 0444 diff --git a/include/os/linux/spl/sys/vmsystm.h b/include/os/linux/spl/sys/vmsystm.h index b3f121ecf0ca..fcd61e818fa3 100644 --- a/include/os/linux/spl/sys/vmsystm.h +++ b/include/os/linux/spl/sys/vmsystm.h @@ -44,7 +44,9 @@ #define zfs_totalhigh_pages totalhigh_pages #endif +#define membar_consumer() smp_rmb() #define membar_producer() smp_wmb() + #define physmem zfs_totalram_pages #define xcopyin(from, to, size) copy_from_user(to, from, size) diff --git a/include/os/linux/zfs/sys/trace_acl.h b/include/os/linux/zfs/sys/trace_acl.h index 4707fc6f4112..21bcefa4ea26 100644 --- a/include/os/linux/zfs/sys/trace_acl.h +++ b/include/os/linux/zfs/sys/trace_acl.h @@ -62,7 +62,6 @@ DECLARE_EVENT_CLASS(zfs_ace_class, __field(boolean_t, z_is_sa) __field(boolean_t, z_is_mapped) __field(boolean_t, z_is_ctldir) - __field(boolean_t, z_is_stale) __field(uint32_t, i_uid) __field(uint32_t, i_gid) @@ -95,7 +94,6 @@ DECLARE_EVENT_CLASS(zfs_ace_class, __entry->z_is_sa = zn->z_is_sa; __entry->z_is_mapped = zn->z_is_mapped; __entry->z_is_ctldir = zn->z_is_ctldir; - __entry->z_is_stale = zn->z_is_stale; __entry->i_uid = KUID_TO_SUID(ZTOI(zn)->i_uid); __entry->i_gid = KGID_TO_SGID(ZTOI(zn)->i_gid); @@ -117,7 +115,7 @@ DECLARE_EVENT_CLASS(zfs_ace_class, "zn_prefetch %u blksz %u seq %u " "mapcnt %llu size %llu pflags %llu " "sync_cnt %u mode 0x%x is_sa %d " - "is_mapped %d is_ctldir %d is_stale %d inode { " + "is_mapped %d is_ctldir %d inode { " "uid %u gid %u ino %lu nlink %u size %lli " "blkbits %u bytes %u mode 0x%x generation %x } } " "ace { type %u flags %u access_mask %u } mask_matched %u", @@ -126,7 +124,7 @@ DECLARE_EVENT_CLASS(zfs_ace_class, __entry->z_seq, __entry->z_mapcnt, __entry->z_size, __entry->z_pflags, __entry->z_sync_cnt, __entry->z_mode, __entry->z_is_sa, __entry->z_is_mapped, - __entry->z_is_ctldir, __entry->z_is_stale, __entry->i_uid, + __entry->z_is_ctldir, __entry->i_uid, __entry->i_gid, __entry->i_ino, __entry->i_nlink, __entry->i_size, __entry->i_blkbits, __entry->i_bytes, __entry->i_mode, __entry->i_generation, diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h index e4fbcff3b853..ac3948a7b628 100644 --- a/include/os/linux/zfs/sys/zpl.h +++ b/include/os/linux/zfs/sys/zpl.h @@ -49,6 +49,8 @@ extern const struct inode_operations zpl_dir_inode_operations; #endif extern const struct inode_operations zpl_symlink_inode_operations; extern const struct inode_operations zpl_special_inode_operations; + +/* zpl_file.c */ extern const struct address_space_operations zpl_address_space_operations; extern const struct file_operations zpl_file_operations; extern const struct file_operations zpl_dir_file_operations; diff --git a/include/sys/dmu.h b/include/sys/dmu.h index 070d27fde3a9..7bdd42e8bed4 100644 --- a/include/sys/dmu.h +++ b/include/sys/dmu.h @@ -27,6 +27,7 @@ * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. * Copyright 2013 Saso Kiselkov. All rights reserved. * Copyright (c) 2017, Intel Corporation. + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -142,6 +143,12 @@ typedef enum dmu_object_byteswap { #define DMU_OT_IS_DDT(ot) \ ((ot) == DMU_OT_DDT_ZAP) +#define DMU_OT_IS_CRITICAL(ot) \ + (DMU_OT_IS_METADATA(ot) && \ + (ot) != DMU_OT_DNODE && \ + (ot) != DMU_OT_DIRECTORY_CONTENTS && \ + (ot) != DMU_OT_SA) + /* Note: ztest uses DMU_OT_UINT64_OTHER as a proxy for file blocks */ #define DMU_OT_IS_FILE(ot) \ ((ot) == DMU_OT_PLAIN_FILE_CONTENTS || (ot) == DMU_OT_UINT64_OTHER) diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h index d227e9f07ae1..e712ec4639e1 100644 --- a/include/sys/fs/zfs.h +++ b/include/sys/fs/zfs.h @@ -29,6 +29,7 @@ * Copyright (c) 2019 Datto Inc. * Portions Copyright 2010 Robert Milkowski * Copyright (c) 2021, Colm Buckley + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ #ifndef _SYS_FS_ZFS_H @@ -424,7 +425,9 @@ typedef enum { typedef enum { ZFS_REDUNDANT_METADATA_ALL, - ZFS_REDUNDANT_METADATA_MOST + ZFS_REDUNDANT_METADATA_MOST, + ZFS_REDUNDANT_METADATA_SOME, + ZFS_REDUNDANT_METADATA_NONE } zfs_redundant_metadata_type_t; typedef enum { diff --git a/include/sys/zfs_znode.h b/include/sys/zfs_znode.h index 84a18159424e..045de01f106e 100644 --- a/include/sys/zfs_znode.h +++ b/include/sys/zfs_znode.h @@ -190,7 +190,6 @@ typedef struct znode { boolean_t z_is_sa; /* are we native sa? */ boolean_t z_is_mapped; /* are we mmap'ed */ boolean_t z_is_ctldir; /* are we .zfs entry */ - boolean_t z_is_stale; /* are we stale due to rollback? */ boolean_t z_suspended; /* extra ref from a suspend? */ uint_t z_blksz; /* block size in bytes */ uint_t z_seq; /* modification sequence number */ diff --git a/lib/libspl/os/linux/zone.c b/lib/libspl/os/linux/zone.c index a71c4e0b275b..393a16ad5cdd 100644 --- a/lib/libspl/os/linux/zone.c +++ b/lib/libspl/os/linux/zone.c @@ -26,7 +26,7 @@ #include zoneid_t -getzoneid() +getzoneid(void) { return (GLOBAL_ZONEID); } diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index f0c2db81102a..cd57a54e4a90 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -59,8 +59,8 @@ static boolean_t zpool_vdev_is_interior(const char *name); typedef struct prop_flags { - int create:1; /* Validate property on creation */ - int import:1; /* Validate property on import */ + unsigned int create:1; /* Validate property on creation */ + unsigned int import:1; /* Validate property on import */ } prop_flags_t; /* @@ -4832,8 +4832,8 @@ zpool_load_compat(const char *compat, boolean_t *features, char *report, for (uint_t i = 0; i < SPA_FEATURES; i++) features[i] = B_TRUE; - char err_badfile[1024] = ""; - char err_badtoken[1024] = ""; + char err_badfile[ZFS_MAXPROPLEN] = ""; + char err_badtoken[ZFS_MAXPROPLEN] = ""; /* * We ignore errors from the directory open() diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index 812d883408a2..7d0fecd9cfe3 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -4048,8 +4048,8 @@ zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type, * properties: if we're asked to exclude this kind of * values we remove them from "recvprops" input nvlist. */ - if (!zfs_prop_inheritable(prop) && - !zfs_prop_user(name) && /* can be inherited too */ + if (!zfs_prop_user(name) && /* can be inherited too */ + !zfs_prop_inheritable(prop) && nvlist_exists(recvprops, name)) fnvlist_remove(recvprops, name); else diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index 7dd38bb3d838..3adb785ddae2 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -170,6 +170,8 @@ libzfs_error_description(libzfs_handle_t *hdl) return (dgettext(TEXT_DOMAIN, "I/O error")); case EZFS_INTR: return (dgettext(TEXT_DOMAIN, "signal received")); + case EZFS_CKSUM: + return (dgettext(TEXT_DOMAIN, "insufficient replicas")); case EZFS_ISSPARE: return (dgettext(TEXT_DOMAIN, "device is reserved as a hot " "spare")); @@ -392,6 +394,10 @@ zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt, case EINTR: zfs_verror(hdl, EZFS_INTR, fmt, ap); return (-1); + + case ECKSUM: + zfs_verror(hdl, EZFS_CKSUM, fmt, ap); + return (-1); } return (0); @@ -674,7 +680,7 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) case ENOSPC: case EDQUOT: zfs_verror(hdl, EZFS_NOSPC, fmt, ap); - return (-1); + break; case EAGAIN: zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, diff --git a/lib/libzfs_core/libzfs_core.c b/lib/libzfs_core/libzfs_core.c index 1e6bbcd561fa..9b2050c67628 100644 --- a/lib/libzfs_core/libzfs_core.c +++ b/lib/libzfs_core/libzfs_core.c @@ -233,7 +233,7 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name, break; } } - if (zc.zc_nvlist_dst_filled) { + if (zc.zc_nvlist_dst_filled && resultp != NULL) { *resultp = fnvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst, zc.zc_nvlist_dst_size); } @@ -890,7 +890,8 @@ recv_impl(const char *snapname, nvlist_t *recvdprops, nvlist_t *localprops, fnvlist_free(outnvl); } else { zfs_cmd_t zc = {"\0"}; - char *packed = NULL; + char *rp_packed = NULL; + char *lp_packed = NULL; size_t size; ASSERT3S(g_refcount, >, 0); @@ -899,14 +900,14 @@ recv_impl(const char *snapname, nvlist_t *recvdprops, nvlist_t *localprops, (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value)); if (recvdprops != NULL) { - packed = fnvlist_pack(recvdprops, &size); - zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed; + rp_packed = fnvlist_pack(recvdprops, &size); + zc.zc_nvlist_src = (uint64_t)(uintptr_t)rp_packed; zc.zc_nvlist_src_size = size; } if (localprops != NULL) { - packed = fnvlist_pack(localprops, &size); - zc.zc_nvlist_conf = (uint64_t)(uintptr_t)packed; + lp_packed = fnvlist_pack(localprops, &size); + zc.zc_nvlist_conf = (uint64_t)(uintptr_t)lp_packed; zc.zc_nvlist_conf_size = size; } @@ -941,8 +942,10 @@ recv_impl(const char *snapname, nvlist_t *recvdprops, nvlist_t *localprops, zc.zc_nvlist_dst_size, errors, KM_SLEEP)); } - if (packed != NULL) - fnvlist_pack_free(packed, size); + if (rp_packed != NULL) + fnvlist_pack_free(rp_packed, size); + if (lp_packed != NULL) + fnvlist_pack_free(lp_packed, size); free((void *)(uintptr_t)zc.zc_nvlist_dst); } diff --git a/lib/libzpool/util.c b/lib/libzpool/util.c index 20cabe7c2e29..f4e33140b6df 100644 --- a/lib/libzpool/util.c +++ b/lib/libzpool/util.c @@ -173,12 +173,13 @@ set_global_var_parse_kv(const char *arg, char **k_out, u_longlong_t *v_out) goto err_free; } - *k_out = k; + *k_out = strdup(k); *v_out = val; + free(d); return (0); err_free: - free(k); + free(d); return (err); } @@ -227,13 +228,14 @@ set_global_var(char const *arg) fprintf(stderr, "Failed to open libzpool.so to set global " "variable\n"); ret = EIO; - goto out_dlclose; + goto out_free; } ret = 0; out_dlclose: dlclose(zpoolhdl); +out_free: free(varname); out_ret: return (ret); diff --git a/lib/libzutil/os/linux/zutil_device_path_os.c b/lib/libzutil/os/linux/zutil_device_path_os.c index 45a6f6f5935b..e443899bf139 100644 --- a/lib/libzutil/os/linux/zutil_device_path_os.c +++ b/lib/libzutil/os/linux/zutil_device_path_os.c @@ -265,7 +265,6 @@ zfs_get_pci_slots_sys_path(const char *dev_name) free(address2); if (asprintf(&path, "/sys/bus/pci/slots/%s", ep->d_name) == -1) { - free(tmp); continue; } break; diff --git a/lib/libzutil/zutil_import.c b/lib/libzutil/zutil_import.c index 8d68f66a4aa5..435a6a059d7b 100644 --- a/lib/libzutil/zutil_import.c +++ b/lib/libzutil/zutil_import.c @@ -490,11 +490,9 @@ get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok, uint64_t guid; uint_t children = 0; nvlist_t **child = NULL; - uint_t holes; uint64_t *hole_array, max_id; uint_t c; boolean_t isactive; - uint64_t hostid; nvlist_t *nvl; boolean_t valid_top_config = B_FALSE; @@ -502,7 +500,8 @@ get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok, goto nomem; for (pe = pl->pools; pe != NULL; pe = pe->pe_next) { - uint64_t id, max_txg = 0; + uint64_t id, max_txg = 0, hostid = 0; + uint_t holes = 0; if (nvlist_alloc(&config, NV_UNIQUE_NAME, 0) != 0) goto nomem; diff --git a/man/man4/zfs.4 b/man/man4/zfs.4 index 390054c2ef8b..06bf33b44621 100644 --- a/man/man4/zfs.4 +++ b/man/man4/zfs.4 @@ -1222,6 +1222,13 @@ Ideally, this will be at least the sum of each queue's .Sy max_active . .No See Sx ZFS I/O SCHEDULER . . +.It Sy zfs_vdev_open_timeout_ms Ns = Ns Sy 1000 Pq uint +Timeout value to wait before determining a device is missing +during import. +This is helpful for transient missing paths due +to links being briefly removed and recreated in response to +udev events. +. .It Sy zfs_vdev_rebuild_max_active Ns = Ns Sy 3 Pq int Maximum sequential resilver I/O operations active to each device. .No See Sx ZFS I/O SCHEDULER . @@ -1651,7 +1658,7 @@ prefetched during a pool traversal, like .Nm zfs Cm send or other data crawling operations. . -.It Sy zfs_per_txg_dirty_frees_percent Ns = Ns Sy 5 Ns % Pq ulong +.It Sy zfs_per_txg_dirty_frees_percent Ns = Ns Sy 30 Ns % Pq ulong Control percentage of dirtied indirect blocks from frees allowed into one TXG. After this threshold is crossed, additional frees will wait until the next TXG. .Sy 0 No disables this throttle. diff --git a/man/man7/zfsprops.7 b/man/man7/zfsprops.7 index d232eb3aeaca..4a5484cca531 100644 --- a/man/man7/zfsprops.7 +++ b/man/man7/zfsprops.7 @@ -36,8 +36,9 @@ .\" Copyright 2018 Nexenta Systems, Inc. .\" Copyright 2019 Joyent, Inc. .\" Copyright (c) 2019, Kjeld Schouten-Lebbing +.\" Copyright (c) 2022 Hewlett Packard Enterprise Development LP. .\" -.Dd May 24, 2021 +.Dd July 21, 2022 .Dt ZFSPROPS 7 .Os . @@ -1450,7 +1451,7 @@ affects only files created afterward; existing files are unaffected. .Pp This property can also be referred to by its shortened column name, .Sy recsize . -.It Sy redundant_metadata Ns = Ns Sy all Ns | Ns Sy most +.It Sy redundant_metadata Ns = Ns Sy all Ns | Ns Sy most Ns | Ns Sy some Ns | Ns Sy none Controls what types of metadata are stored redundantly. ZFS stores an extra copy of metadata, so that if a single block is corrupted, the amount of user data lost is limited. @@ -1482,7 +1483,7 @@ When set to ZFS stores an extra copy of most types of metadata. This can improve performance of random writes, because less metadata must be written. -In practice, at worst about 100 blocks +In practice, at worst about 1000 blocks .Po of .Sy recordsize bytes each @@ -1491,6 +1492,17 @@ of user data can be lost if a single on-disk block is corrupt. The exact behavior of which metadata blocks are stored redundantly may change in future releases. .Pp +When set to +.Sy some , +ZFS stores an extra copy of only critical metadata. +This can improve file create performance since less metadata needs to be written. +If a single on-disk block is corrupt, at worst a single user file can be lost. +.Pp +When set to +.Sy none , +ZFS does not store any copies of metadata redundantly. +If a single on-disk block is corrupt, an entire dataset can be lost. +.Pp The default value is .Sy all . .It Sy refquota Ns = Ns Ar size Ns | Ns Sy none diff --git a/module/icp/Makefile.in b/module/icp/Makefile.in index 54b5df1a1987..ce84999ad1cf 100644 --- a/module/icp/Makefile.in +++ b/module/icp/Makefile.in @@ -60,12 +60,9 @@ $(MODULE)-$(CONFIG_X86) += algs/modes/gcm_pclmulqdq.o $(MODULE)-$(CONFIG_X86) += algs/aes/aes_impl_aesni.o $(MODULE)-$(CONFIG_X86) += algs/aes/aes_impl_x86-64.o -# Suppress objtool "can't find jump dest instruction at" warnings. They -# are caused by the constants which are defined in the text section of the -# assembly file using .byte instructions (e.g. bswap_mask). The objtool -# utility tries to interpret them as opcodes and obviously fails doing so. +# Suppress objtool "return with modified stack frame" warnings. OBJECT_FILES_NON_STANDARD_aesni-gcm-x86_64.o := y -OBJECT_FILES_NON_STANDARD_ghash-x86_64.o := y + # Suppress objtool "unsupported stack pointer realignment" warnings. We are # not using a DRAP register while aligning the stack to a 64 byte boundary. # See #6950 for the reasoning. diff --git a/module/icp/asm-x86_64/aes/aes_amd64.S b/module/icp/asm-x86_64/aes/aes_amd64.S index 931d2480609c..e631752af65e 100644 --- a/module/icp/asm-x86_64/aes/aes_amd64.S +++ b/module/icp/asm-x86_64/aes/aes_amd64.S @@ -704,6 +704,7 @@ enc_tab: ENTRY_NP(aes_encrypt_amd64) + ENDBR #ifdef GLADMAN_INTERFACE // Original interface sub $[4*8], %rsp // gnu/linux/opensolaris binary interface @@ -809,6 +810,7 @@ dec_tab: ENTRY_NP(aes_decrypt_amd64) + ENDBR #ifdef GLADMAN_INTERFACE // Original interface sub $[4*8], %rsp // gnu/linux/opensolaris binary interface diff --git a/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S b/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S index 70e419c2e4ab..cf17b3768712 100644 --- a/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S +++ b/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S @@ -47,6 +47,9 @@ #if defined(__x86_64__) && defined(HAVE_AVX) && \ defined(HAVE_AES) && defined(HAVE_PCLMULQDQ) +#define _ASM +#include + .extern gcm_avx_can_use_movbe .text @@ -56,6 +59,7 @@ .align 32 _aesni_ctr32_ghash_6x: .cfi_startproc + ENDBR vmovdqu 32(%r11),%xmm2 subq $6,%rdx vpxor %xmm4,%xmm4,%xmm4 @@ -363,7 +367,7 @@ _aesni_ctr32_ghash_6x: vpxor 16+8(%rsp),%xmm8,%xmm8 vpxor %xmm4,%xmm8,%xmm8 - .byte 0xf3,0xc3 + RET .cfi_endproc .size _aesni_ctr32_ghash_6x,.-_aesni_ctr32_ghash_6x #endif /* ifdef HAVE_MOVBE */ @@ -372,6 +376,7 @@ _aesni_ctr32_ghash_6x: .align 32 _aesni_ctr32_ghash_no_movbe_6x: .cfi_startproc + ENDBR vmovdqu 32(%r11),%xmm2 subq $6,%rdx vpxor %xmm4,%xmm4,%xmm4 @@ -691,7 +696,7 @@ _aesni_ctr32_ghash_no_movbe_6x: vpxor 16+8(%rsp),%xmm8,%xmm8 vpxor %xmm4,%xmm8,%xmm8 - .byte 0xf3,0xc3 + RET .cfi_endproc .size _aesni_ctr32_ghash_no_movbe_6x,.-_aesni_ctr32_ghash_no_movbe_6x @@ -700,6 +705,7 @@ _aesni_ctr32_ghash_no_movbe_6x: .align 32 aesni_gcm_decrypt: .cfi_startproc + ENDBR xorq %r10,%r10 cmpq $0x60,%rdx jb .Lgcm_dec_abort @@ -810,13 +816,14 @@ aesni_gcm_decrypt: .cfi_def_cfa_register %rsp .Lgcm_dec_abort: movq %r10,%rax - .byte 0xf3,0xc3 + RET .cfi_endproc .size aesni_gcm_decrypt,.-aesni_gcm_decrypt .type _aesni_ctr32_6x,@function .align 32 _aesni_ctr32_6x: .cfi_startproc + ENDBR vmovdqu 0-128(%rcx),%xmm4 vmovdqu 32(%r11),%xmm2 leaq -2(%rbp),%r13 // ICP uses 10,12,14 not 9,11,13 for rounds. @@ -880,7 +887,7 @@ _aesni_ctr32_6x: vmovups %xmm14,80(%rsi) leaq 96(%rsi),%rsi - .byte 0xf3,0xc3 + RET .align 32 .Lhandle_ctr32_2: vpshufb %xmm0,%xmm1,%xmm6 @@ -911,6 +918,7 @@ _aesni_ctr32_6x: .align 32 aesni_gcm_encrypt: .cfi_startproc + ENDBR xorq %r10,%r10 cmpq $288,%rdx jb .Lgcm_enc_abort @@ -1186,7 +1194,7 @@ aesni_gcm_encrypt: .cfi_def_cfa_register %rsp .Lgcm_enc_abort: movq %r10,%rax - .byte 0xf3,0xc3 + RET .cfi_endproc .size aesni_gcm_encrypt,.-aesni_gcm_encrypt @@ -1239,6 +1247,7 @@ atomic_toggle_boolean_nv: RET .size atomic_toggle_boolean_nv,.-atomic_toggle_boolean_nv +.pushsection .rodata .align 64 .Lbswap_mask: .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 @@ -1252,6 +1261,7 @@ atomic_toggle_boolean_nv: .byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .byte 65,69,83,45,78,73,32,71,67,77,32,109,111,100,117,108,101,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .align 64 +.popsection /* Mark the stack non-executable. */ #if defined(__linux__) && defined(__ELF__) diff --git a/module/icp/asm-x86_64/modes/ghash-x86_64.S b/module/icp/asm-x86_64/modes/ghash-x86_64.S index 90cc36b43a78..bf3724a23eae 100644 --- a/module/icp/asm-x86_64/modes/ghash-x86_64.S +++ b/module/icp/asm-x86_64/modes/ghash-x86_64.S @@ -97,6 +97,9 @@ #if defined(__x86_64__) && defined(HAVE_AVX) && \ defined(HAVE_AES) && defined(HAVE_PCLMULQDQ) +#define _ASM +#include + .text .globl gcm_gmult_clmul @@ -104,6 +107,7 @@ .align 16 gcm_gmult_clmul: .cfi_startproc + ENDBR .L_gmult_clmul: movdqu (%rdi),%xmm0 movdqa .Lbswap_mask(%rip),%xmm5 @@ -149,7 +153,7 @@ gcm_gmult_clmul: pxor %xmm1,%xmm0 .byte 102,15,56,0,197 movdqu %xmm0,(%rdi) - .byte 0xf3,0xc3 + RET .cfi_endproc .size gcm_gmult_clmul,.-gcm_gmult_clmul @@ -158,6 +162,7 @@ gcm_gmult_clmul: .align 32 gcm_init_htab_avx: .cfi_startproc + ENDBR vzeroupper vmovdqu (%rsi),%xmm2 @@ -262,7 +267,7 @@ gcm_init_htab_avx: vmovdqu %xmm5,-16(%rdi) vzeroupper - .byte 0xf3,0xc3 + RET .cfi_endproc .size gcm_init_htab_avx,.-gcm_init_htab_avx @@ -271,6 +276,7 @@ gcm_init_htab_avx: .align 32 gcm_gmult_avx: .cfi_startproc + ENDBR jmp .L_gmult_clmul .cfi_endproc .size gcm_gmult_avx,.-gcm_gmult_avx @@ -279,6 +285,7 @@ gcm_gmult_avx: .align 32 gcm_ghash_avx: .cfi_startproc + ENDBR vzeroupper vmovdqu (%rdi),%xmm10 @@ -649,9 +656,11 @@ gcm_ghash_avx: vpshufb %xmm13,%xmm10,%xmm10 vmovdqu %xmm10,(%rdi) vzeroupper - .byte 0xf3,0xc3 + RET .cfi_endproc .size gcm_ghash_avx,.-gcm_ghash_avx + +.pushsection .rodata .align 64 .Lbswap_mask: .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 @@ -705,6 +714,7 @@ gcm_ghash_avx: .byte 71,72,65,83,72,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .align 64 +.popsection /* Mark the stack non-executable. */ #if defined(__linux__) && defined(__ELF__) diff --git a/module/icp/asm-x86_64/sha2/sha256_impl.S b/module/icp/asm-x86_64/sha2/sha256_impl.S index 31da7f9767df..fc0c68ba2c12 100644 --- a/module/icp/asm-x86_64/sha2/sha256_impl.S +++ b/module/icp/asm-x86_64/sha2/sha256_impl.S @@ -84,6 +84,7 @@ SHA256TransformBlocks(SHA2_CTX *ctx, const void *in, size_t num) ENTRY_NP(SHA256TransformBlocks) .cfi_startproc + ENDBR movq %rsp, %rax .cfi_def_cfa_register %rax push %rbx diff --git a/module/icp/asm-x86_64/sha2/sha512_impl.S b/module/icp/asm-x86_64/sha2/sha512_impl.S index c2ba18538e33..ab9474a4e2bb 100644 --- a/module/icp/asm-x86_64/sha2/sha512_impl.S +++ b/module/icp/asm-x86_64/sha2/sha512_impl.S @@ -85,6 +85,7 @@ SHA512TransformBlocks(SHA2_CTX *ctx, const void *in, size_t num) ENTRY_NP(SHA512TransformBlocks) .cfi_startproc + ENDBR movq %rsp, %rax .cfi_def_cfa_register %rax push %rbx diff --git a/module/icp/core/kcf_mech_tabs.c b/module/icp/core/kcf_mech_tabs.c index 2642b317d698..00a76217ff50 100644 --- a/module/icp/core/kcf_mech_tabs.c +++ b/module/icp/core/kcf_mech_tabs.c @@ -720,8 +720,8 @@ kcf_remove_mech_provider(char *mech_name, kcf_provider_desc_t *prov_desc) } /* free entry */ - KCF_PROV_REFRELE(prov_mech->pm_prov_desc); KCF_PROV_IREFRELE(prov_mech->pm_prov_desc); + KCF_PROV_REFRELE(prov_mech->pm_prov_desc); kmem_free(prov_mech, sizeof (kcf_prov_mech_desc_t)); } diff --git a/module/icp/core/kcf_prov_tabs.c b/module/icp/core/kcf_prov_tabs.c index 9d303d022517..3b0bf12e7b73 100644 --- a/module/icp/core/kcf_prov_tabs.c +++ b/module/icp/core/kcf_prov_tabs.c @@ -171,8 +171,8 @@ kcf_prov_tab_rem_provider(crypto_provider_id_t prov_id) * at that time. */ - KCF_PROV_REFRELE(prov_desc); KCF_PROV_IREFRELE(prov_desc); + KCF_PROV_REFRELE(prov_desc); return (CRYPTO_SUCCESS); } diff --git a/module/icp/core/kcf_sched.c b/module/icp/core/kcf_sched.c index 81fd15f8ea26..fa44a4dbf864 100644 --- a/module/icp/core/kcf_sched.c +++ b/module/icp/core/kcf_sched.c @@ -1274,7 +1274,7 @@ kcf_aop_done(kcf_areq_node_t *areq, int error) * Allocate the thread pool and initialize all the fields. */ static void -kcfpool_alloc() +kcfpool_alloc(void) { kcfpool = kmem_alloc(sizeof (kcf_pool_t), KM_SLEEP); diff --git a/module/icp/include/sys/ia32/asm_linkage.h b/module/icp/include/sys/ia32/asm_linkage.h index 876e21e5f1b1..beb3592f3d73 100644 --- a/module/icp/include/sys/ia32/asm_linkage.h +++ b/module/icp/include/sys/ia32/asm_linkage.h @@ -30,9 +30,29 @@ #include #include -#if defined(__linux__) && defined(CONFIG_SLS) -#define RET ret; int3 -#else +#if defined(_KERNEL) && defined(__linux__) +#include +#endif + +#ifndef ENDBR +#if defined(__ELF__) && defined(__CET__) && defined(__has_include) +/* CSTYLED */ +#if __has_include() + +#include + +#ifdef _CET_ENDBR +#define ENDBR _CET_ENDBR +#endif /* _CET_ENDBR */ + +#endif /* */ +#endif /* __ELF__ && __CET__ && __has_include */ +#endif /* !ENDBR */ + +#ifndef ENDBR +#define ENDBR +#endif +#ifndef RET #define RET ret #endif @@ -204,6 +224,7 @@ sym1 = sym2 * insert the calls to mcount for profiling. ENTRY_NP is identical, but * never calls mcount. */ +#undef ENTRY #define ENTRY(x) \ .text; \ .align ASM_ENTRY_ALIGN; \ diff --git a/module/icp/io/sha2_mod.c b/module/icp/io/sha2_mod.c index d690cd0bcb05..f3125ad84528 100644 --- a/module/icp/io/sha2_mod.c +++ b/module/icp/io/sha2_mod.c @@ -823,12 +823,15 @@ sha2_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, */ if (mechanism->cm_type % 3 == 2) { if (mechanism->cm_param == NULL || - mechanism->cm_param_len != sizeof (ulong_t)) - ret = CRYPTO_MECHANISM_PARAM_INVALID; - PROV_SHA2_GET_DIGEST_LEN(mechanism, - PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len); - if (PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len > sha_digest_len) + mechanism->cm_param_len != sizeof (ulong_t)) { ret = CRYPTO_MECHANISM_PARAM_INVALID; + } else { + PROV_SHA2_GET_DIGEST_LEN(mechanism, + PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len); + if (PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len > + sha_digest_len) + ret = CRYPTO_MECHANISM_PARAM_INVALID; + } } if (ret != CRYPTO_SUCCESS) { diff --git a/module/lua/lapi.c b/module/lua/lapi.c index 6a845c461052..75f8b2a1dd6f 100644 --- a/module/lua/lapi.c +++ b/module/lua/lapi.c @@ -251,6 +251,8 @@ LUA_API int lua_type (lua_State *L, int idx) { LUA_API const char *lua_typename (lua_State *L, int t) { UNUSED(L); + if (t > 8 || t < 0) + return "internal_type_error"; return ttypename(t); } diff --git a/module/lua/lobject.c b/module/lua/lobject.c index 024d3199fe24..5d88d36c5fd7 100644 --- a/module/lua/lobject.c +++ b/module/lua/lobject.c @@ -144,7 +144,7 @@ static lua_Number lua_strx2number (const char *s, char **endptr) { *endptr = cast(char *, s); /* valid up to here */ ret: if (neg) r = -r; - return (r * (1 << e)); + return ((e >= 0) ? (r * (1ULL << e)) : (r / (1ULL << -e))); } #endif diff --git a/module/lua/setjmp/setjmp_x86_64.S b/module/lua/setjmp/setjmp_x86_64.S index 34cf2c7dce93..47c886709c2a 100644 --- a/module/lua/setjmp/setjmp_x86_64.S +++ b/module/lua/setjmp/setjmp_x86_64.S @@ -23,7 +23,15 @@ * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ +#if defined(_KERNEL) && defined(__linux__) +#include +#endif + +#ifndef RET +#define RET ret +#endif +#undef ENTRY #define ENTRY(x) \ .text; \ .align 8; \ @@ -34,13 +42,6 @@ x: #define SET_SIZE(x) \ .size x, [.-x] - -#if defined(__linux__) && defined(CONFIG_SLS) -#define RET ret; int3 -#else -#define RET ret -#endif - /* * Setjmp and longjmp implement non-local gotos using state vectors * type label_t. diff --git a/module/os/freebsd/zfs/spa_os.c b/module/os/freebsd/zfs/spa_os.c index d5f851a30860..a5445fa565e7 100644 --- a/module/os/freebsd/zfs/spa_os.c +++ b/module/os/freebsd/zfs/spa_os.c @@ -250,7 +250,7 @@ spa_import_rootpool(const char *name, bool checkpointrewind) mutex_exit(&spa_namespace_lock); fnvlist_free(config); cmn_err(CE_NOTE, "Can not parse the config for pool '%s'", - pname); + name); return (error); } diff --git a/module/os/freebsd/zfs/zfs_ioctl_compat.c b/module/os/freebsd/zfs/zfs_ioctl_compat.c index 81967bed73f9..43156f2c6366 100644 --- a/module/os/freebsd/zfs/zfs_ioctl_compat.c +++ b/module/os/freebsd/zfs/zfs_ioctl_compat.c @@ -319,7 +319,7 @@ zfs_ioctl_legacy_to_ozfs(int request) int zfs_ioctl_ozfs_to_legacy(int request) { - if (request > ZFS_IOC_LAST) + if (request >= ZFS_IOC_LAST) return (-1); if (request > ZFS_IOC_PLATFORM) { diff --git a/module/os/linux/spl/spl-procfs-list.c b/module/os/linux/spl/spl-procfs-list.c index 2cba1a3022e0..71b7f75a2a94 100644 --- a/module/os/linux/spl/spl-procfs-list.c +++ b/module/os/linux/spl/spl-procfs-list.c @@ -23,9 +23,9 @@ */ #include -#include #include #include +#include /* * A procfs_list is a wrapper around a linked list which implements the seq_file diff --git a/module/os/linux/zfs/vdev_disk.c b/module/os/linux/zfs/vdev_disk.c index 6b6d119e4717..60b111c59f23 100644 --- a/module/os/linux/zfs/vdev_disk.c +++ b/module/os/linux/zfs/vdev_disk.c @@ -56,7 +56,7 @@ static void *zfs_vdev_holder = VDEV_HOLDER; * device is missing. The missing path may be transient since the links * can be briefly removed and recreated in response to udev events. */ -static unsigned zfs_vdev_open_timeout_ms = 1000; +static uint_t zfs_vdev_open_timeout_ms = 1000; /* * Size of the "reserved" partition, in blocks. @@ -1040,3 +1040,6 @@ param_set_max_auto_ashift(const char *buf, zfs_kernel_param_t *kp) return (0); } + +ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, open_timeout_ms, UINT, ZMOD_RW, + "Timeout before determining that a device is missing"); diff --git a/module/os/linux/zfs/zfs_ctldir.c b/module/os/linux/zfs/zfs_ctldir.c index d33188f3822c..c45644a69153 100644 --- a/module/os/linux/zfs/zfs_ctldir.c +++ b/module/os/linux/zfs/zfs_ctldir.c @@ -470,7 +470,6 @@ zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id, zp->z_is_sa = B_FALSE; zp->z_is_mapped = B_FALSE; zp->z_is_ctldir = B_TRUE; - zp->z_is_stale = B_FALSE; zp->z_sa_hdl = NULL; zp->z_blksz = 0; zp->z_seq = 0; diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c index daada0a7757d..3880a6b94a05 100644 --- a/module/os/linux/zfs/zfs_vfsops.c +++ b/module/os/linux/zfs/zfs_vfsops.c @@ -809,9 +809,7 @@ zfsvfs_create(const char *osname, boolean_t readonly, zfsvfs_t **zfvp) } error = zfsvfs_create_impl(zfvp, zfsvfs, os); - if (error != 0) { - dmu_objset_disown(os, B_TRUE, zfsvfs); - } + return (error); } @@ -851,6 +849,7 @@ zfsvfs_create_impl(zfsvfs_t **zfvp, zfsvfs_t *zfsvfs, objset_t *os) error = zfsvfs_init(zfsvfs, os); if (error != 0) { + dmu_objset_disown(os, B_TRUE, zfsvfs); *zfvp = NULL; zfsvfs_free(zfsvfs); return (error); @@ -1552,6 +1551,7 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent) error = zfs_root(zfsvfs, &root_inode); if (error) { (void) zfs_umount(sb); + zfsvfs = NULL; /* avoid double-free; first in zfs_umount */ goto out; } @@ -1559,6 +1559,7 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent) sb->s_root = d_make_root(root_inode); if (sb->s_root == NULL) { (void) zfs_umount(sb); + zfsvfs = NULL; /* avoid double-free; first in zfs_umount */ error = SET_ERROR(ENOMEM); goto out; } @@ -1877,7 +1878,6 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds) if (err2) { zpl_d_drop_aliases(ZTOI(zp)); remove_inode_hash(ZTOI(zp)); - zp->z_is_stale = B_TRUE; } /* see comment in zfs_suspend_fs() */ diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c index 0a697b1adb76..d915dd122297 100644 --- a/module/os/linux/zfs/zfs_znode.c +++ b/module/os/linux/zfs/zfs_znode.c @@ -549,7 +549,6 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz, zp->z_atime_dirty = B_FALSE; zp->z_is_mapped = B_FALSE; zp->z_is_ctldir = B_FALSE; - zp->z_is_stale = B_FALSE; zp->z_suspended = B_FALSE; zp->z_sa_hdl = NULL; zp->z_mapcnt = 0; diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c index c54647cb3c85..c4fac173cc8d 100644 --- a/module/os/linux/zfs/zpl_xattr.c +++ b/module/os/linux/zfs/zpl_xattr.c @@ -1991,7 +1991,9 @@ zpl_xattr_permission(xattr_filldir_t *xf, const char *name, int name_len) return (perm); } -#if !defined(HAVE_POSIX_ACL_RELEASE) || defined(HAVE_POSIX_ACL_RELEASE_GPL_ONLY) +#if defined(CONFIG_FS_POSIX_ACL) && \ + (!defined(HAVE_POSIX_ACL_RELEASE) || \ + defined(HAVE_POSIX_ACL_RELEASE_GPL_ONLY)) struct acl_rel_struct { struct acl_rel_struct *next; struct posix_acl *acl; diff --git a/module/zcommon/zfs_prop.c b/module/zcommon/zfs_prop.c index 2171b61122a4..313a3788e140 100644 --- a/module/zcommon/zfs_prop.c +++ b/module/zcommon/zfs_prop.c @@ -25,6 +25,7 @@ * Copyright 2016, Joyent, Inc. * Copyright (c) 2019, Klara Inc. * Copyright (c) 2019, Allan Jude + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -371,6 +372,8 @@ zfs_prop_init(void) static zprop_index_t redundant_metadata_table[] = { { "all", ZFS_REDUNDANT_METADATA_ALL }, { "most", ZFS_REDUNDANT_METADATA_MOST }, + { "some", ZFS_REDUNDANT_METADATA_SOME }, + { "none", ZFS_REDUNDANT_METADATA_NONE }, { NULL } }; @@ -387,7 +390,7 @@ zfs_prop_init(void) zprop_register_index(ZFS_PROP_REDUNDANT_METADATA, "redundant_metadata", ZFS_REDUNDANT_METADATA_ALL, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "all | most", "REDUND_MD", + "all | most | some | none", "REDUND_MD", redundant_metadata_table); zprop_register_index(ZFS_PROP_SYNC, "sync", ZFS_SYNC_STANDARD, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, @@ -718,6 +721,8 @@ zfs_prop_init(void) boolean_t zfs_prop_delegatable(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); zprop_desc_t *pd = &zfs_prop_table[prop]; /* The mlslabel property is never delegatable. */ @@ -840,6 +845,8 @@ zfs_prop_valid_for_type(int prop, zfs_type_t types, boolean_t headcheck) zprop_type_t zfs_prop_get_type(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_proptype); } @@ -849,6 +856,8 @@ zfs_prop_get_type(zfs_prop_t prop) boolean_t zfs_prop_readonly(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_attr == PROP_READONLY || zfs_prop_table[prop].pd_attr == PROP_ONETIME || zfs_prop_table[prop].pd_attr == PROP_ONETIME_DEFAULT); @@ -860,6 +869,8 @@ zfs_prop_readonly(zfs_prop_t prop) boolean_t zfs_prop_visible(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_visible && zfs_prop_table[prop].pd_zfs_mod_supported); } @@ -870,6 +881,8 @@ zfs_prop_visible(zfs_prop_t prop) boolean_t zfs_prop_setonce(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_attr == PROP_ONETIME || zfs_prop_table[prop].pd_attr == PROP_ONETIME_DEFAULT); } @@ -877,12 +890,16 @@ zfs_prop_setonce(zfs_prop_t prop) const char * zfs_prop_default_string(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_strdefault); } uint64_t zfs_prop_default_numeric(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_numdefault); } @@ -893,6 +910,8 @@ zfs_prop_default_numeric(zfs_prop_t prop) const char * zfs_prop_to_name(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_name); } @@ -902,6 +921,8 @@ zfs_prop_to_name(zfs_prop_t prop) boolean_t zfs_prop_inheritable(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_attr == PROP_INHERIT || zfs_prop_table[prop].pd_attr == PROP_ONETIME); } @@ -954,6 +975,8 @@ zfs_prop_valid_keylocation(const char *str, boolean_t encrypted) const char * zfs_prop_values(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_values); } @@ -965,6 +988,8 @@ zfs_prop_values(zfs_prop_t prop) int zfs_prop_is_string(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_proptype == PROP_TYPE_STRING || zfs_prop_table[prop].pd_proptype == PROP_TYPE_INDEX); } @@ -976,6 +1001,8 @@ zfs_prop_is_string(zfs_prop_t prop) const char * zfs_prop_column_name(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_colname); } @@ -986,6 +1013,8 @@ zfs_prop_column_name(zfs_prop_t prop) boolean_t zfs_prop_align_right(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_rightalign); } diff --git a/module/zfs/arc.c b/module/zfs/arc.c index fedcc8ac13cc..200de769aafa 100644 --- a/module/zfs/arc.c +++ b/module/zfs/arc.c @@ -4470,7 +4470,7 @@ arc_evict_meta_balanced(uint64_t meta_used) * meta buffers. Requests to the upper layers will be made with * increasingly large scan sizes until the ARC is below the limit. */ - if (meta_used > arc_meta_limit) { + if (meta_used > arc_meta_limit || arc_available_memory() < 0) { if (type == ARC_BUFC_DATA) { type = ARC_BUFC_METADATA; } else { @@ -5176,7 +5176,7 @@ arc_adapt(int bytes, arc_state_t *state) atomic_add_64(&arc_c, (int64_t)bytes); if (arc_c > arc_c_max) arc_c = arc_c_max; - else if (state == arc_anon) + else if (state == arc_anon && arc_p < arc_c >> 1) atomic_add_64(&arc_p, (int64_t)bytes); if (arc_p > arc_c) arc_p = arc_c; @@ -5389,7 +5389,8 @@ arc_get_data_impl(arc_buf_hdr_t *hdr, uint64_t size, void *tag, if (aggsum_upper_bound(&arc_sums.arcstat_size) < arc_c && hdr->b_l1hdr.b_state == arc_anon && (zfs_refcount_count(&arc_anon->arcs_size) + - zfs_refcount_count(&arc_mru->arcs_size) > arc_p)) + zfs_refcount_count(&arc_mru->arcs_size) > arc_p && + arc_p < arc_c >> 1)) arc_p = MIN(arc_c, arc_p + size); } } diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c index 7ecc2812b4e4..53f5775c9e8e 100644 --- a/module/zfs/dbuf.c +++ b/module/zfs/dbuf.c @@ -3300,10 +3300,10 @@ dbuf_prefetch_indirect_done(zio_t *zio, const zbookmark_phys_t *zb, blkptr_t *bp = ((blkptr_t *)abuf->b_data) + P2PHASE(nextblkid, 1ULL << dpa->dpa_epbs); - ASSERT(!BP_IS_REDACTED(bp) || + ASSERT(!BP_IS_REDACTED(bp) || (dpa->dpa_dnode && dsl_dataset_feature_is_active( dpa->dpa_dnode->dn_objset->os_dsl_dataset, - SPA_FEATURE_REDACTED_DATASETS)); + SPA_FEATURE_REDACTED_DATASETS))); if (BP_IS_HOLE(bp) || BP_IS_REDACTED(bp)) { dbuf_prefetch_fini(dpa, B_TRUE); } else if (dpa->dpa_curlevel == dpa->dpa_zb.zb_level) { diff --git a/module/zfs/dmu.c b/module/zfs/dmu.c index e38c9b452a28..c67a36470e33 100644 --- a/module/zfs/dmu.c +++ b/module/zfs/dmu.c @@ -28,6 +28,7 @@ * Copyright (c) 2019 Datto Inc. * Copyright (c) 2019, Klara Inc. * Copyright (c) 2019, Allan Jude + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ #include @@ -70,7 +71,7 @@ int zfs_nopwrite_enabled = 1; * will wait until the next TXG. * A value of zero will disable this throttle. */ -unsigned long zfs_per_txg_dirty_frees_percent = 5; +unsigned long zfs_per_txg_dirty_frees_percent = 30; /* * Enable/disable forcing txg sync when dirty checking for holes with lseek(). @@ -1988,12 +1989,22 @@ dmu_write_policy(objset_t *os, dnode_t *dn, int level, int wp, zio_prop_t *zp) ZCHECKSUM_FLAG_EMBEDDED)) checksum = ZIO_CHECKSUM_FLETCHER_4; - if (os->os_redundant_metadata == ZFS_REDUNDANT_METADATA_ALL || - (os->os_redundant_metadata == - ZFS_REDUNDANT_METADATA_MOST && - (level >= zfs_redundant_metadata_most_ditto_level || - DMU_OT_IS_METADATA(type) || (wp & WP_SPILL)))) + switch (os->os_redundant_metadata) { + case ZFS_REDUNDANT_METADATA_ALL: copies++; + break; + case ZFS_REDUNDANT_METADATA_MOST: + if (level >= zfs_redundant_metadata_most_ditto_level || + DMU_OT_IS_METADATA(type) || (wp & WP_SPILL)) + copies++; + break; + case ZFS_REDUNDANT_METADATA_SOME: + if (DMU_OT_IS_CRITICAL(type)) + copies++; + break; + case ZFS_REDUNDANT_METADATA_NONE: + break; + } } else if (wp & WP_NOFILL) { ASSERT(level == 0); diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c index a8975797e8af..5ad3b2f269d6 100644 --- a/module/zfs/dmu_objset.c +++ b/module/zfs/dmu_objset.c @@ -32,6 +32,7 @@ * Copyright (c) 2018, loli10K . All rights reserved. * Copyright (c) 2019, Klara Inc. * Copyright (c) 2019, Allan Jude + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -287,7 +288,9 @@ redundant_metadata_changed_cb(void *arg, uint64_t newval) * Inheritance and range checking should have been done by now. */ ASSERT(newval == ZFS_REDUNDANT_METADATA_ALL || - newval == ZFS_REDUNDANT_METADATA_MOST); + newval == ZFS_REDUNDANT_METADATA_MOST || + newval == ZFS_REDUNDANT_METADATA_SOME || + newval == ZFS_REDUNDANT_METADATA_NONE); os->os_redundant_metadata = newval; } diff --git a/module/zfs/dmu_recv.c b/module/zfs/dmu_recv.c index 99eeceeb4139..98ca2b3bcec1 100644 --- a/module/zfs/dmu_recv.c +++ b/module/zfs/dmu_recv.c @@ -602,7 +602,7 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx) * so add the DS_HOLD_FLAG_DECRYPT flag only if we are dealing * with a dataset we may encrypt. */ - if (drba->drba_dcp != NULL && + if (drba->drba_dcp == NULL || drba->drba_dcp->cp_crypt != ZIO_CRYPT_OFF) { dsflags |= DS_HOLD_FLAG_DECRYPT; } diff --git a/module/zfs/dmu_send.c b/module/zfs/dmu_send.c index 390afba92680..20ec4ac1739d 100644 --- a/module/zfs/dmu_send.c +++ b/module/zfs/dmu_send.c @@ -2716,6 +2716,10 @@ dmu_send_obj(const char *pool, uint64_t tosnap, uint64_t fromsnap, dspp.numfromredactsnaps = NUM_SNAPS_NOT_REDACTED; err = dmu_send_impl(&dspp); } + if (dspp.fromredactsnaps) + kmem_free(dspp.fromredactsnaps, + dspp.numfromredactsnaps * sizeof (uint64_t)); + dsl_dataset_rele(dspp.to_ds, FTAG); return (err); } @@ -2924,6 +2928,10 @@ dmu_send(const char *tosnap, const char *fromsnap, boolean_t embedok, /* dmu_send_impl will call dsl_pool_rele for us. */ err = dmu_send_impl(&dspp); } else { + if (dspp.fromredactsnaps) + kmem_free(dspp.fromredactsnaps, + dspp.numfromredactsnaps * + sizeof (uint64_t)); dsl_pool_rele(dspp.dp, FTAG); } } else { diff --git a/module/zfs/dsl_crypt.c b/module/zfs/dsl_crypt.c index 1ea184de338c..bf1f55e68ff5 100644 --- a/module/zfs/dsl_crypt.c +++ b/module/zfs/dsl_crypt.c @@ -2672,6 +2672,7 @@ spa_do_crypt_objset_mac_abd(boolean_t generate, spa_t *spa, uint64_t dsobj, objset_phys_t *osp = buf; uint8_t portable_mac[ZIO_OBJSET_MAC_LEN]; uint8_t local_mac[ZIO_OBJSET_MAC_LEN]; + const uint8_t zeroed_mac[ZIO_OBJSET_MAC_LEN] = {0}; /* look up the key from the spa's keystore */ ret = spa_keystore_lookup_key(spa, dsobj, FTAG, &dck); @@ -2694,10 +2695,24 @@ spa_do_crypt_objset_mac_abd(boolean_t generate, spa_t *spa, uint64_t dsobj, return (0); } - if (bcmp(portable_mac, osp->os_portable_mac, ZIO_OBJSET_MAC_LEN) != 0 || - bcmp(local_mac, osp->os_local_mac, ZIO_OBJSET_MAC_LEN) != 0) { - abd_return_buf(abd, buf, datalen); - return (SET_ERROR(ECKSUM)); + if (memcmp(portable_mac, osp->os_portable_mac, + ZIO_OBJSET_MAC_LEN) != 0 || + memcmp(local_mac, osp->os_local_mac, ZIO_OBJSET_MAC_LEN) != 0) { + /* + * If the MAC is zeroed out, we failed to decrypt it. + * This should only arise, at least on Linux, + * if we hit edge case handling for useraccounting, since we + * shouldn't get here without bailing out on error earlier + * otherwise. + * + * So if we're in that case, we can just fall through and + * special-casing noticing that it's zero will handle it + * elsewhere, since we can just regenerate it. + */ + if (memcmp(local_mac, zeroed_mac, ZIO_OBJSET_MAC_LEN) != 0) { + abd_return_buf(abd, buf, datalen); + return (SET_ERROR(ECKSUM)); + } } abd_return_buf(abd, buf, datalen); diff --git a/module/zfs/dsl_dataset.c b/module/zfs/dsl_dataset.c index b7894b9802cc..cd16a11757e6 100644 --- a/module/zfs/dsl_dataset.c +++ b/module/zfs/dsl_dataset.c @@ -1747,6 +1747,21 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname, } } + /* + * We are not allowed to dirty a filesystem when done receiving + * a snapshot. In this case the flag SPA_FEATURE_LARGE_BLOCKS will + * not be set and a subsequent encrypted raw send will fail. Hence + * activate this feature if needed here. + */ + for (spa_feature_t f = 0; f < SPA_FEATURES; f++) { + if (zfeature_active(f, ds->ds_feature_activation[f]) && + !(zfeature_active(f, ds->ds_feature[f]))) { + dsl_dataset_activate_feature(dsobj, f, + ds->ds_feature_activation[f], tx); + ds->ds_feature[f] = ds->ds_feature_activation[f]; + } + } + ASSERT3U(ds->ds_prev != 0, ==, dsl_dataset_phys(ds)->ds_prev_snap_obj != 0); if (ds->ds_prev) { @@ -3309,7 +3324,6 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx) dsl_pool_t *dp = dmu_tx_pool(tx); dsl_dataset_t *hds; struct promotenode *snap; - dsl_dataset_t *origin_ds, *origin_head; int err; uint64_t unused; uint64_t ss_mv_cnt; @@ -3329,12 +3343,11 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx) } snap = list_head(&ddpa->shared_snaps); - origin_head = snap->ds; if (snap == NULL) { err = SET_ERROR(ENOENT); goto out; } - origin_ds = snap->ds; + dsl_dataset_t *const origin_ds = snap->ds; /* * Encrypted clones share a DSL Crypto Key with their origin's dsl dir. @@ -3430,10 +3443,10 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx) * Check that bookmarks that are being transferred don't have * name conflicts. */ - for (dsl_bookmark_node_t *dbn = avl_first(&origin_head->ds_bookmarks); + for (dsl_bookmark_node_t *dbn = avl_first(&origin_ds->ds_bookmarks); dbn != NULL && dbn->dbn_phys.zbm_creation_txg <= dsl_dataset_phys(origin_ds)->ds_creation_txg; - dbn = AVL_NEXT(&origin_head->ds_bookmarks, dbn)) { + dbn = AVL_NEXT(&origin_ds->ds_bookmarks, dbn)) { if (strlen(dbn->dbn_name) >= max_snap_len) { err = SET_ERROR(ENAMETOOLONG); goto out; diff --git a/module/zfs/dsl_deadlist.c b/module/zfs/dsl_deadlist.c index a77e381520db..7681b735ec70 100644 --- a/module/zfs/dsl_deadlist.c +++ b/module/zfs/dsl_deadlist.c @@ -1028,8 +1028,13 @@ dsl_process_sub_livelist(bpobj_t *bpobj, bplist_t *to_free, zthr_t *t, .t = t }; int err = bpobj_iterate_nofree(bpobj, dsl_livelist_iterate, &arg, size); + VERIFY(err != 0 || avl_numnodes(&avl) == 0); - VERIFY0(avl_numnodes(&avl)); + void *cookie = NULL; + livelist_entry_t *le = NULL; + while ((le = avl_destroy_nodes(&avl, &cookie)) != NULL) { + kmem_free(le, sizeof (livelist_entry_t)); + } avl_destroy(&avl); return (err); } diff --git a/module/zfs/dsl_dir.c b/module/zfs/dsl_dir.c index 1431fb98e6b7..b600584d4bec 100644 --- a/module/zfs/dsl_dir.c +++ b/module/zfs/dsl_dir.c @@ -817,6 +817,18 @@ dsl_fs_ss_limit_check(dsl_dir_t *dd, uint64_t delta, zfs_prop_t prop, ASSERT(prop == ZFS_PROP_FILESYSTEM_LIMIT || prop == ZFS_PROP_SNAPSHOT_LIMIT); + if (prop == ZFS_PROP_SNAPSHOT_LIMIT) { + /* + * We don't enforce the limit for temporary snapshots. This is + * indicated by a NULL cred_t argument. + */ + if (cr == NULL) + return (0); + + count_prop = DD_FIELD_SNAPSHOT_COUNT; + } else { + count_prop = DD_FIELD_FILESYSTEM_COUNT; + } /* * If we're allowed to change the limit, don't enforce the limit * e.g. this can happen if a snapshot is taken by an administrative @@ -836,19 +848,6 @@ dsl_fs_ss_limit_check(dsl_dir_t *dd, uint64_t delta, zfs_prop_t prop, if (delta == 0) return (0); - if (prop == ZFS_PROP_SNAPSHOT_LIMIT) { - /* - * We don't enforce the limit for temporary snapshots. This is - * indicated by a NULL cred_t argument. - */ - if (cr == NULL) - return (0); - - count_prop = DD_FIELD_SNAPSHOT_COUNT; - } else { - count_prop = DD_FIELD_FILESYSTEM_COUNT; - } - /* * If an ancestor has been provided, stop checking the limit once we * hit that dir. We need this during rename so that we don't overcount @@ -1270,6 +1269,7 @@ dsl_dir_tempreserve_impl(dsl_dir_t *dd, uint64_t asize, boolean_t netfree, uint64_t quota; struct tempreserve *tr; int retval; + uint64_t ext_quota; uint64_t ref_rsrv; top_of_function: @@ -1345,7 +1345,16 @@ dsl_dir_tempreserve_impl(dsl_dir_t *dd, uint64_t asize, boolean_t netfree, * on-disk is over quota and there are no pending changes * or deferred frees (which may free up space for us). */ - if (used_on_disk + est_inflight >= quota) { + ext_quota = quota >> 5; + if (quota == UINT64_MAX) + ext_quota = 0; + + if (used_on_disk >= quota) { + /* Quota exceeded */ + mutex_exit(&dd->dd_lock); + DMU_TX_STAT_BUMP(dmu_tx_quota); + return (retval); + } else if (used_on_disk + est_inflight >= quota + ext_quota) { if (est_inflight > 0 || used_on_disk < quota) { retval = SET_ERROR(ERESTART); } else { diff --git a/module/zfs/dsl_prop.c b/module/zfs/dsl_prop.c index 0089edf8683a..6cba8bd206a5 100644 --- a/module/zfs/dsl_prop.c +++ b/module/zfs/dsl_prop.c @@ -23,6 +23,7 @@ * Copyright (c) 2012, 2015 by Delphix. All rights reserved. * Copyright (c) 2013 Martin Matuska. All rights reserved. * Copyright 2019 Joyent, Inc. + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ #include @@ -41,6 +42,7 @@ #define ZPROP_INHERIT_SUFFIX "$inherit" #define ZPROP_RECVD_SUFFIX "$recvd" +#define ZPROP_IUV_SUFFIX "$iuv" static int dodefault(zfs_prop_t prop, int intsz, int numints, void *buf) @@ -69,6 +71,17 @@ dodefault(zfs_prop_t prop, int intsz, int numints, void *buf) return (0); } +static int +dsl_prop_known_index(zfs_prop_t prop, uint64_t value) +{ + const char *str = NULL; + if (prop != ZPROP_CONT && prop != ZPROP_INVAL && + zfs_prop_get_type(prop) == PROP_TYPE_INDEX) + return (!zfs_prop_index_to_string(prop, value, &str)); + + return (-1); +} + int dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, int intsz, int numints, void *buf, char *setpoint, boolean_t snapshot) @@ -81,6 +94,7 @@ dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, boolean_t inheriting = B_FALSE; char *inheritstr; char *recvdstr; + char *iuvstr; ASSERT(dsl_pool_config_held(dd->dd_pool)); @@ -91,6 +105,7 @@ dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, inheritable = (prop == ZPROP_INVAL || zfs_prop_inheritable(prop)); inheritstr = kmem_asprintf("%s%s", propname, ZPROP_INHERIT_SUFFIX); recvdstr = kmem_asprintf("%s%s", propname, ZPROP_RECVD_SUFFIX); + iuvstr = kmem_asprintf("%s%s", propname, ZPROP_IUV_SUFFIX); /* * Note: dd may become NULL, therefore we shouldn't dereference it @@ -105,6 +120,18 @@ dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, inheriting = B_TRUE; } + /* Check for a iuv value. */ + err = zap_lookup(mos, dsl_dir_phys(dd)->dd_props_zapobj, + iuvstr, intsz, numints, buf); + if (dsl_prop_known_index(zfs_name_to_prop(propname), + *(uint64_t *)buf) != 1) + err = ENOENT; + if (err != ENOENT) { + if (setpoint != NULL && err == 0) + dsl_dir_name(dd, setpoint); + break; + } + /* Check for a local value. */ err = zap_lookup(mos, dsl_dir_phys(dd)->dd_props_zapobj, propname, intsz, numints, buf); @@ -155,6 +182,7 @@ dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, kmem_strfree(inheritstr); kmem_strfree(recvdstr); + kmem_strfree(iuvstr); return (err); } @@ -647,6 +675,45 @@ dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj, dsl_dir_rele(dd, FTAG); } + +/* + * For newer values in zfs index type properties, we add a new key + * propname$iuv (iuv = Ignore Unknown Values) to the properties zap object + * to store the new property value and store the default value in the + * existing prop key. So that the propname$iuv key is ignored by the older zfs + * versions and the default property value from the existing prop key is + * used. + */ +static void +dsl_prop_set_iuv(objset_t *mos, uint64_t zapobj, const char *propname, + int intsz, int numints, const void *value, dmu_tx_t *tx) +{ + char *iuvstr = kmem_asprintf("%s%s", propname, ZPROP_IUV_SUFFIX); + boolean_t iuv = B_FALSE; + zfs_prop_t prop = zfs_name_to_prop(propname); + + switch (prop) { + case ZFS_PROP_REDUNDANT_METADATA: + if (*(uint64_t *)value == ZFS_REDUNDANT_METADATA_SOME || + *(uint64_t *)value == ZFS_REDUNDANT_METADATA_NONE) + iuv = B_TRUE; + break; + default: + break; + } + + if (iuv) { + VERIFY0(zap_update(mos, zapobj, iuvstr, intsz, numints, + value, tx)); + uint64_t val = zfs_prop_default_numeric(prop); + VERIFY0(zap_update(mos, zapobj, propname, intsz, numints, + &val, tx)); + } else { + zap_remove(mos, zapobj, iuvstr, tx); + } + kmem_strfree(iuvstr); +} + void dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, zprop_source_t source, int intsz, int numints, const void *value, @@ -659,6 +726,7 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, const char *valstr = NULL; char *inheritstr; char *recvdstr; + char *iuvstr; char *tbuf = NULL; int err; uint64_t version = spa_version(ds->ds_dir->dd_pool->dp_spa); @@ -692,6 +760,7 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, inheritstr = kmem_asprintf("%s%s", propname, ZPROP_INHERIT_SUFFIX); recvdstr = kmem_asprintf("%s%s", propname, ZPROP_RECVD_SUFFIX); + iuvstr = kmem_asprintf("%s%s", propname, ZPROP_IUV_SUFFIX); switch ((int)source) { case ZPROP_SRC_NONE: @@ -709,11 +778,14 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, /* * remove propname$inherit * set propname -> value + * set propname$iuv -> new property value */ err = zap_remove(mos, zapobj, inheritstr, tx); ASSERT(err == 0 || err == ENOENT); VERIFY0(zap_update(mos, zapobj, propname, intsz, numints, value, tx)); + (void) dsl_prop_set_iuv(mos, zapobj, propname, intsz, + numints, value, tx); break; case ZPROP_SRC_INHERITED: /* @@ -723,6 +795,8 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, */ err = zap_remove(mos, zapobj, propname, tx); ASSERT(err == 0 || err == ENOENT); + err = zap_remove(mos, zapobj, iuvstr, tx); + ASSERT(err == 0 || err == ENOENT); if (version >= SPA_VERSION_RECVD_PROPS && dsl_prop_get_int_ds(ds, ZPROP_HAS_RECVD, &dummy) == 0) { dummy = 0; @@ -763,6 +837,7 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, kmem_strfree(inheritstr); kmem_strfree(recvdstr); + kmem_strfree(iuvstr); /* * If we are left with an empty snap zap we can destroy it. @@ -1012,6 +1087,14 @@ dsl_prop_get_all_impl(objset_t *mos, uint64_t propobj, propname = za.za_name; source = setpoint; + + /* Skip if iuv entries are preset. */ + valstr = kmem_asprintf("%s%s", propname, + ZPROP_IUV_SUFFIX); + err = zap_contains(mos, propobj, valstr); + kmem_strfree(valstr); + if (err == 0) + continue; } else if (strcmp(suffix, ZPROP_INHERIT_SUFFIX) == 0) { /* Skip explicitly inherited entries. */ continue; @@ -1044,6 +1127,16 @@ dsl_prop_get_all_impl(objset_t *mos, uint64_t propobj, source = ((flags & DSL_PROP_GET_INHERITING) ? setpoint : ZPROP_SOURCE_VAL_RECVD); + } else if (strcmp(suffix, ZPROP_IUV_SUFFIX) == 0) { + (void) strlcpy(buf, za.za_name, + MIN(sizeof (buf), suffix - za.za_name + 1)); + propname = buf; + source = setpoint; + prop = zfs_name_to_prop(propname); + + if (dsl_prop_known_index(prop, + za.za_first_integer) != 1) + continue; } else { /* * For backward compatibility, skip suffixes we don't diff --git a/module/zfs/fm.c b/module/zfs/fm.c index 7981568b8df7..cfd1372c5b97 100644 --- a/module/zfs/fm.c +++ b/module/zfs/fm.c @@ -953,6 +953,7 @@ fm_fmri_hc_create(nvlist_t *fmri, int version, const nvlist_t *auth, } atomic_inc_64( &erpt_kstat_data.fmri_set_failed.value.ui64); + va_end(ap); return; } } diff --git a/module/zfs/metaslab.c b/module/zfs/metaslab.c index ecc70298dc79..74796096d794 100644 --- a/module/zfs/metaslab.c +++ b/module/zfs/metaslab.c @@ -5207,12 +5207,11 @@ metaslab_alloc_dva(spa_t *spa, metaslab_class_t *mc, uint64_t psize, ASSERT(mg->mg_initialized); /* - * Avoid writing single-copy data to a failing, + * Avoid writing single-copy data to an unhealthy, * non-redundant vdev, unless we've already tried all * other vdevs. */ - if ((vd->vdev_stat.vs_write_errors > 0 || - vd->vdev_state < VDEV_STATE_HEALTHY) && + if (vd->vdev_state < VDEV_STATE_HEALTHY && d == 0 && !try_hard && vd->vdev_children == 0) { metaslab_trace_add(zal, mg, NULL, psize, d, TRACE_VDEV_ERROR, allocator); diff --git a/module/zfs/spa.c b/module/zfs/spa.c index 569d2b7a61df..2625479f19d5 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -5239,7 +5239,7 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy, * If we've recovered the pool, pass back any information we * gathered while doing the load. */ - if (state == SPA_LOAD_RECOVER) { + if (state == SPA_LOAD_RECOVER && config != NULL) { fnvlist_add_nvlist(*config, ZPOOL_CONFIG_LOAD_INFO, spa->spa_load_info); } @@ -6781,10 +6781,12 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing, return (spa_vdev_exit(spa, newrootvd, txg, error)); /* - * Spares can't replace logs + * log, dedup and special vdevs should not be replaced by spares. */ - if (oldvd->vdev_top->vdev_islog && newvd->vdev_isspare) + if ((oldvd->vdev_top->vdev_alloc_bias != VDEV_BIAS_NONE || + oldvd->vdev_top->vdev_islog) && newvd->vdev_isspare) { return (spa_vdev_exit(spa, newrootvd, txg, ENOTSUP)); + } /* * A dRAID spare can only replace a child of its parent dRAID vdev. diff --git a/module/zfs/spa_log_spacemap.c b/module/zfs/spa_log_spacemap.c index 0dfe5b8395e0..6a27f5759549 100644 --- a/module/zfs/spa_log_spacemap.c +++ b/module/zfs/spa_log_spacemap.c @@ -690,7 +690,8 @@ spa_estimate_metaslabs_to_flush(spa_t *spa) * based on the incoming rate until we exceed it. */ if (available_blocks >= 0 && available_txgs >= 0) { - uint64_t skip_txgs = MIN(available_txgs + 1, + uint64_t skip_txgs = (incoming == 0) ? + available_txgs + 1 : MIN(available_txgs + 1, (available_blocks / incoming) + 1); available_blocks -= (skip_txgs * incoming); available_txgs -= skip_txgs; diff --git a/module/zfs/vdev_rebuild.c b/module/zfs/vdev_rebuild.c index 4d7de0c6c44c..9dfbe0cf6f30 100644 --- a/module/zfs/vdev_rebuild.c +++ b/module/zfs/vdev_rebuild.c @@ -22,6 +22,7 @@ * * Copyright (c) 2018, Intel Corporation. * Copyright (c) 2020 by Lawrence Livermore National Security, LLC. + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ #include @@ -134,6 +135,7 @@ int zfs_rebuild_scrub_enabled = 1; * For vdev_rebuild_initiate_sync() and vdev_rebuild_reset_sync(). */ static void vdev_rebuild_thread(void *arg); +static void vdev_rebuild_reset_sync(void *arg, dmu_tx_t *tx); /* * Clear the per-vdev rebuild bytes value for a vdev tree. @@ -307,6 +309,17 @@ vdev_rebuild_complete_sync(void *arg, dmu_tx_t *tx) vdev_rebuild_phys_t *vrp = &vr->vr_rebuild_phys; mutex_enter(&vd->vdev_rebuild_lock); + + /* + * Handle a second device failure if it occurs after all rebuild I/O + * has completed but before this sync task has been executed. + */ + if (vd->vdev_rebuild_reset_wanted) { + mutex_exit(&vd->vdev_rebuild_lock); + vdev_rebuild_reset_sync(arg, tx); + return; + } + vrp->vrp_rebuild_state = VDEV_REBUILD_COMPLETE; vrp->vrp_end_time = gethrestime_sec(); @@ -760,7 +773,6 @@ vdev_rebuild_thread(void *arg) ASSERT(vd->vdev_rebuilding); ASSERT(spa_feature_is_active(spa, SPA_FEATURE_DEVICE_REBUILD)); ASSERT3B(vd->vdev_rebuild_cancel_wanted, ==, B_FALSE); - ASSERT3B(vd->vdev_rebuild_reset_wanted, ==, B_FALSE); vdev_rebuild_t *vr = &vd->vdev_rebuild_config; vdev_rebuild_phys_t *vrp = &vr->vr_rebuild_phys; diff --git a/module/zfs/vdev_removal.c b/module/zfs/vdev_removal.c index 48bd20b2169f..12cc654c8d18 100644 --- a/module/zfs/vdev_removal.c +++ b/module/zfs/vdev_removal.c @@ -2056,7 +2056,6 @@ spa_vdev_remove_top_check(vdev_t *vd) * and not be raidz or draid. */ vdev_t *rvd = spa->spa_root_vdev; - int num_indirect = 0; for (uint64_t id = 0; id < rvd->vdev_children; id++) { vdev_t *cvd = rvd->vdev_child[id]; @@ -2072,8 +2071,6 @@ spa_vdev_remove_top_check(vdev_t *vd) if (cvd->vdev_ashift != 0 && cvd->vdev_alloc_bias == VDEV_BIAS_NONE) ASSERT3U(cvd->vdev_ashift, ==, spa->spa_max_ashift); - if (cvd->vdev_ops == &vdev_indirect_ops) - num_indirect++; if (!vdev_is_concrete(cvd)) continue; if (vdev_get_nparity(cvd) != 0) diff --git a/module/zfs/vdev_trim.c b/module/zfs/vdev_trim.c index 2bae33b2b532..92daed48f3d5 100644 --- a/module/zfs/vdev_trim.c +++ b/module/zfs/vdev_trim.c @@ -1188,12 +1188,11 @@ vdev_autotrim_thread(void *arg) mutex_exit(&vd->vdev_autotrim_lock); spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER); - uint64_t extent_bytes_max = zfs_trim_extent_bytes_max; - uint64_t extent_bytes_min = zfs_trim_extent_bytes_min; - while (!vdev_autotrim_should_stop(vd)) { int txgs_per_trim = MAX(zfs_trim_txg_batch, 1); boolean_t issued_trim = B_FALSE; + uint64_t extent_bytes_max = zfs_trim_extent_bytes_max; + uint64_t extent_bytes_min = zfs_trim_extent_bytes_min; /* * All of the metaslabs are divided in to groups of size diff --git a/module/zfs/zap_micro.c b/module/zfs/zap_micro.c index 590e2f837ba2..e3dadf130413 100644 --- a/module/zfs/zap_micro.c +++ b/module/zfs/zap_micro.c @@ -1011,8 +1011,10 @@ zap_lookup_impl(zap_t *zap, const char *name, } else { *(uint64_t *)buf = MZE_PHYS(zap, mze)->mze_value; - (void) strlcpy(realname, - MZE_PHYS(zap, mze)->mze_name, rn_len); + if (realname != NULL) + (void) strlcpy(realname, + MZE_PHYS(zap, mze)->mze_name, + rn_len); if (ncp) { *ncp = mzap_normalization_conflict(zap, zn, mze, &idx); diff --git a/module/zfs/zcp.c b/module/zfs/zcp.c index f200b928bc6d..3f11445f74c8 100644 --- a/module/zfs/zcp.c +++ b/module/zfs/zcp.c @@ -277,9 +277,9 @@ zcp_table_to_nvlist(lua_State *state, int index, int depth) } break; case LUA_TNUMBER: - VERIFY3U(sizeof (buf), >, - snprintf(buf, sizeof (buf), "%lld", - (longlong_t)lua_tonumber(state, -2))); + (void) snprintf(buf, sizeof (buf), "%lld", + (longlong_t)lua_tonumber(state, -2)); + key = buf; if (saw_str_could_collide) { key_could_collide = B_TRUE; diff --git a/module/zfs/zfs_fm.c b/module/zfs/zfs_fm.c index a05ff7330458..b1c3f7a6301c 100644 --- a/module/zfs/zfs_fm.c +++ b/module/zfs/zfs_fm.c @@ -253,7 +253,6 @@ void zfs_ereport_clear(spa_t *spa, vdev_t *vd) { uint64_t vdev_guid, pool_guid; - int cnt = 0; ASSERT(vd != NULL || spa != NULL); if (vd == NULL) { @@ -277,7 +276,6 @@ zfs_ereport_clear(spa_t *spa, vdev_t *vd) avl_remove(&recent_events_tree, entry); list_remove(&recent_events_list, entry); kmem_free(entry, sizeof (*entry)); - cnt++; } } diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 1951a3fecebd..758baa60ba4e 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -7404,7 +7404,7 @@ zfsdev_get_state_impl(minor_t minor, enum zfsdev_state_type which) for (zs = zfsdev_state_list; zs != NULL; zs = zs->zs_next) { if (zs->zs_minor == minor) { - smp_rmb(); + membar_consumer(); switch (which) { case ZST_ONEXIT: return (zs->zs_onexit); diff --git a/module/zfs/zil.c b/module/zfs/zil.c index b9f177daee53..11e05e477839 100644 --- a/module/zfs/zil.c +++ b/module/zfs/zil.c @@ -397,8 +397,18 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func, error = zil_read_log_block(zilog, decrypt, &blk, &next_blk, lrbuf, &end); - if (error != 0) + if (error != 0) { + if (claimed) { + char name[ZFS_MAX_DATASET_NAME_LEN]; + + dmu_objset_name(zilog->zl_os, name); + + cmn_err(CE_WARN, "ZFS read log block error %d, " + "dataset %s, seq 0x%llx\n", error, name, + (u_longlong_t)blk_seq); + } break; + } for (lrp = lrbuf; lrp < end; lrp += reclen) { lr_t *lr = (lr_t *)lrp; @@ -422,10 +432,6 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func, zilog->zl_parse_blk_count = blk_count; zilog->zl_parse_lr_count = lr_count; - ASSERT(!claimed || !(zh->zh_flags & ZIL_CLAIM_LR_SEQ_VALID) || - (max_blk_seq == claim_blk_seq && max_lr_seq == claim_lr_seq) || - (decrypt && error == EIO)); - zil_bp_tree_fini(zilog); zio_buf_free(lrbuf, SPA_OLD_MAXBLOCKSIZE); diff --git a/scripts/enum-extract.pl b/scripts/enum-extract.pl index 5112cc807f67..5dc2e3455145 100755 --- a/scripts/enum-extract.pl +++ b/scripts/enum-extract.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl my $usage = < /pool_lb/pwd" + +log_must zfs create -o recordsize=1m pool_lb/fs +log_must dd if=/dev/urandom of=$file bs=1024 count=1024 +log_must zfs snapshot pool_lb/fs@snap1 + +log_must eval "zfs send -L pool_lb/fs@snap1 > $backup" +log_must eval "zfs recv -o encryption=aes-256-ccm -o keyformat=passphrase \ + -o keylocation=file:///pool_lb/pwd -o primarycache=none \ + -o recordsize=1m pool_lb/testfs5 < $backup" + +log_must eval "zfs send --raw pool_lb/testfs5@snap1 > $raw_backup" + +log_pass "Receiving and raw sending a snapshot with large blocks succeeds" diff --git a/tests/zfs-tests/tests/functional/userquota/13709_reproducer.bz2 b/tests/zfs-tests/tests/functional/userquota/13709_reproducer.bz2 new file mode 100644 index 000000000000..9c3168279461 Binary files /dev/null and b/tests/zfs-tests/tests/functional/userquota/13709_reproducer.bz2 differ diff --git a/tests/zfs-tests/tests/functional/userquota/Makefile.am b/tests/zfs-tests/tests/functional/userquota/Makefile.am index 2c94d3e1521c..dad2f8c45d5e 100644 --- a/tests/zfs-tests/tests/functional/userquota/Makefile.am +++ b/tests/zfs-tests/tests/functional/userquota/Makefile.am @@ -22,8 +22,10 @@ dist_pkgdata_SCRIPTS = \ userspace_002_pos.ksh \ userspace_003_pos.ksh \ userspace_encrypted.ksh \ - userspace_send_encrypted.ksh + userspace_send_encrypted.ksh \ + userspace_encrypted_13709.ksh dist_pkgdata_DATA = \ + 13709_reproducer.bz2 \ userquota.cfg \ userquota_common.kshlib diff --git a/tests/zfs-tests/tests/functional/userquota/userspace_encrypted_13709.ksh b/tests/zfs-tests/tests/functional/userquota/userspace_encrypted_13709.ksh new file mode 100755 index 000000000000..9c1d847756d1 --- /dev/null +++ b/tests/zfs-tests/tests/functional/userquota/userspace_encrypted_13709.ksh @@ -0,0 +1,45 @@ +#!/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. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib + +# +# DESCRIPTION: +# Avoid allowing #11294/#13709 to recur a third time. +# +# So we hardcode a copy of a pool with this bug, try unlocking it, +# and fail on error. Simple. + +function cleanup +{ + destroy_pool $POOLNAME + rm -f $FILEDEV +} + +log_onexit cleanup + +FILEDEV="$TEST_BASE_DIR/userspace_13709" +POOLNAME="testpool_13709" + +log_assert "ZFS should be able to unlock pools with #13709's failure mode" + +log_must bzcat $STF_SUITE/tests/functional/userquota/13709_reproducer.bz2 > $FILEDEV + +log_must zpool import -d $FILEDEV $POOLNAME + +echo -e 'password\npassword\n' | log_must zfs mount -al + +# Cleanup +cleanup + +log_pass "#13709 not happening here"